Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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.core; | 5 part of dart.core; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A parsed URI, as specified by RFC-3986, http://tools.ietf.org/html/rfc3986. | 8 * A parsed URI, as specified by RFC-3986, http://tools.ietf.org/html/rfc3986. |
| 9 */ | 9 */ |
| 10 class Uri { | 10 class Uri { |
| 11 final String _host; | |
| 11 int _port; | 12 int _port; |
| 12 String _path; | 13 String _path; |
| 13 | 14 |
| 14 /** | 15 /** |
| 15 * Returns the scheme component. | 16 * Returns the scheme component. |
| 16 * | 17 * |
| 17 * Returns the empty string if there is no scheme component. | 18 * Returns the empty string if there is no scheme component. |
| 18 */ | 19 */ |
| 19 final String scheme; | 20 final String scheme; |
| 20 | 21 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 39 * Returns the empty string if there is no user info in the | 40 * Returns the empty string if there is no user info in the |
| 40 * authority component. | 41 * authority component. |
| 41 */ | 42 */ |
| 42 final String userInfo; | 43 final String userInfo; |
| 43 | 44 |
| 44 /** | 45 /** |
| 45 * Returns the host part of the authority component. | 46 * Returns the host part of the authority component. |
| 46 * | 47 * |
| 47 * Returns the empty string if there is no authority component and | 48 * Returns the empty string if there is no authority component and |
| 48 * hence no host. | 49 * hence no host. |
| 50 * | |
| 51 * If the host is an IP version 6 address, the surrounding `[` and `]` is | |
| 52 * removed. | |
| 49 */ | 53 */ |
| 50 final String host; | 54 String get host { |
| 55 if (_host != null && _host.startsWith('[')) { | |
| 56 return _host.substring(1, _host.length - 1); | |
| 57 } | |
| 58 return _host; | |
| 59 } | |
| 51 | 60 |
| 52 /** | 61 /** |
| 53 * Returns the port part of the authority component. | 62 * Returns the port part of the authority component. |
| 54 * | 63 * |
| 55 * Returns 0 if there is no port in the authority component. | 64 * Returns 0 if there is no port in the authority component. |
| 56 */ | 65 */ |
| 57 int get port => _port; | 66 int get port => _port; |
| 58 | 67 |
| 59 /** | 68 /** |
| 60 * Returns the path component. | 69 * Returns the path component. |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 146 * [queryParameters]. When [query] is used the provided string is | 155 * [queryParameters]. When [query] is used the provided string is |
| 147 * expected to be fully percent-encoded and is used in its literal | 156 * expected to be fully percent-encoded and is used in its literal |
| 148 * form. When [queryParameters] is used the query is built from the | 157 * form. When [queryParameters] is used the query is built from the |
| 149 * provided map. Each key and value in the map is percent-encoded | 158 * provided map. Each key and value in the map is percent-encoded |
| 150 * and joined using equal and ampersand characters. The | 159 * and joined using equal and ampersand characters. The |
| 151 * percent-encoding of the keys and values encodes all characters | 160 * percent-encoding of the keys and values encodes all characters |
| 152 * except for the unreserved characters. | 161 * except for the unreserved characters. |
| 153 * | 162 * |
| 154 * The fragment component is set through [fragment]. | 163 * The fragment component is set through [fragment]. |
| 155 */ | 164 */ |
| 156 Uri({scheme, | 165 Uri({String scheme, |
| 157 this.userInfo: "", | 166 this.userInfo: "", |
| 158 this.host: "", | 167 String host: "", |
| 159 port: 0, | 168 port: 0, |
| 160 String path, | 169 String path, |
| 161 Iterable<String> pathSegments, | 170 Iterable<String> pathSegments, |
| 162 String query, | 171 String query, |
| 163 Map<String, String> queryParameters, | 172 Map<String, String> queryParameters, |
| 164 fragment: ""}) : | 173 fragment: ""}) : |
| 165 scheme = _makeScheme(scheme), | 174 scheme = _makeScheme(scheme), |
| 175 _host = _makeHost(host), | |
| 166 query = _makeQuery(query, queryParameters), | 176 query = _makeQuery(query, queryParameters), |
| 167 fragment = _makeFragment(fragment) { | 177 fragment = _makeFragment(fragment) { |
| 168 // Perform scheme specific normalization. | 178 // Perform scheme specific normalization. |
| 169 if (scheme == "http" && port == 80) { | 179 if (scheme == "http" && port == 80) { |
| 170 _port = 0; | 180 _port = 0; |
| 171 } else if (scheme == "https" && port == 443) { | 181 } else if (scheme == "https" && port == 443) { |
| 172 _port = 0; | 182 _port = 0; |
| 173 } else { | 183 } else { |
| 174 _port = port; | 184 _port = port; |
| 175 } | 185 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 230 // Split off the user info. | 240 // Split off the user info. |
| 231 bool hasUserInfo = false; | 241 bool hasUserInfo = false; |
| 232 for (int i = 0; i < authority.length; i++) { | 242 for (int i = 0; i < authority.length; i++) { |
| 233 if (authority.codeUnitAt(i) == _AT_SIGN) { | 243 if (authority.codeUnitAt(i) == _AT_SIGN) { |
| 234 hasUserInfo = true; | 244 hasUserInfo = true; |
| 235 userInfo = authority.substring(0, i); | 245 userInfo = authority.substring(0, i); |
| 236 hostStart = i + 1; | 246 hostStart = i + 1; |
| 237 break; | 247 break; |
| 238 } | 248 } |
| 239 } | 249 } |
| 250 var hostEnd = hostStart; | |
| 251 if (hostStart < authority.length && | |
| 252 authority.codeUnitAt(hostStart) == _LEFT_BRACKET) { | |
| 253 // IPv6 host. | |
| 254 for (; hostEnd < authority.length; hostEnd++) { | |
| 255 if (authority.codeUnitAt(hostEnd) == _RIGHT_BRACKET) break; | |
| 256 } | |
| 257 if (hostEnd == authority.length) { | |
| 258 throw new FormatException("Invalid IPv6 host entry."); | |
| 259 } | |
| 260 parseIPv6Address(authority.substring(hostStart + 1, hostEnd)); | |
| 261 hostEnd++; // Skip the closing bracket. | |
| 262 if (hostEnd != authority.length && | |
| 263 authority.codeUnitAt(hostEnd) != _COLON) { | |
| 264 throw new FormatException("Invalid end of authority"); | |
| 265 } | |
| 266 } | |
| 240 // Split host and port. | 267 // Split host and port. |
| 241 bool hasPort = false; | 268 bool hasPort = false; |
| 242 for (int i = hostStart; i < authority.length; i++) { | 269 for (; hostEnd < authority.length; hostEnd++) { |
| 243 if (authority.codeUnitAt(i) == _COLON) { | 270 if (authority.codeUnitAt(hostEnd) == _COLON) { |
| 244 hasPort = true; | 271 var portString = authority.substring(hostEnd + 1); |
| 245 host = authority.substring(hostStart, i); | 272 // We allow the empty port - falling back to initial value. |
| 246 if (!host.isEmpty) { | 273 if (portString.isNotEmpty) port = int.parse(portString); |
| 247 var portString = authority.substring(i + 1); | |
| 248 if (portString.isNotEmpty) port = int.parse(portString); | |
| 249 } | |
| 250 break; | 274 break; |
| 251 } | 275 } |
| 252 } | 276 } |
| 253 if (!hasPort) { | 277 host = authority.substring(hostStart, hostEnd); |
| 254 host = hasUserInfo ? authority.substring(hostStart) : authority; | |
| 255 } | |
| 256 | 278 |
| 257 return new Uri(scheme: scheme, | 279 return new Uri(scheme: scheme, |
| 258 userInfo: userInfo, | 280 userInfo: userInfo, |
| 259 host: host, | 281 host: host, |
| 260 port: port, | 282 port: port, |
| 261 pathSegments: unencodedPath.split("/"), | 283 pathSegments: unencodedPath.split("/"), |
| 262 queryParameters: queryParameters); | 284 queryParameters: queryParameters); |
| 263 } | 285 } |
| 264 | 286 |
| 265 /** | 287 /** |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 467 * The returned map is unmodifiable and will throw [UnsupportedError] on any | 489 * The returned map is unmodifiable and will throw [UnsupportedError] on any |
| 468 * calls that would mutate it. | 490 * calls that would mutate it. |
| 469 */ | 491 */ |
| 470 Map<String, String> get queryParameters { | 492 Map<String, String> get queryParameters { |
| 471 if (_queryParameters == null) { | 493 if (_queryParameters == null) { |
| 472 _queryParameters = new _UnmodifiableMap(splitQueryString(query)); | 494 _queryParameters = new _UnmodifiableMap(splitQueryString(query)); |
| 473 } | 495 } |
| 474 return _queryParameters; | 496 return _queryParameters; |
| 475 } | 497 } |
| 476 | 498 |
| 499 static String _makeHost(String host) { | |
| 500 if (host == null || host.isEmpty) return host; | |
| 501 if (host.codeUnitAt(0) == _LEFT_BRACKET) { | |
| 502 if (host.codeUnitAt(host.length - 1) != _RIGHT_BRACKET) { | |
| 503 throw new FormatException('Missing end `]` to match `[` in host'); | |
| 504 } | |
| 505 parseIPv6Address(host.substring(1, host.length - 1)); | |
| 506 return host; | |
| 507 } | |
| 508 for (int i = 0; i < host.length; i++) { | |
| 509 if (host.codeUnitAt(i) == _COLON) { | |
| 510 parseIPv6Address(host); | |
| 511 return '[$host]'; | |
| 512 } | |
| 513 } | |
| 514 return host; | |
| 515 } | |
| 516 | |
| 477 static String _makeScheme(String scheme) { | 517 static String _makeScheme(String scheme) { |
| 478 bool isSchemeLowerCharacter(int ch) { | 518 bool isSchemeLowerCharacter(int ch) { |
| 479 return ch < 128 && | 519 return ch < 128 && |
| 480 ((_schemeLowerTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); | 520 ((_schemeLowerTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); |
| 481 } | 521 } |
| 482 | 522 |
| 483 bool isSchemeCharacter(int ch) { | 523 bool isSchemeCharacter(int ch) { |
| 484 return ch < 128 && ((_schemeTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); | 524 return ch < 128 && ((_schemeTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); |
| 485 } | 525 } |
| 486 | 526 |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 821 | 861 |
| 822 /** | 862 /** |
| 823 * Returns the origin of the URI in the form scheme://host:port for the | 863 * Returns the origin of the URI in the form scheme://host:port for the |
| 824 * schemes http and https. | 864 * schemes http and https. |
| 825 * | 865 * |
| 826 * It is an error if the scheme is not "http" or "https". | 866 * It is an error if the scheme is not "http" or "https". |
| 827 * | 867 * |
| 828 * See: http://www.w3.org/TR/2011/WD-html5-20110405/origin-0.html#origin | 868 * See: http://www.w3.org/TR/2011/WD-html5-20110405/origin-0.html#origin |
| 829 */ | 869 */ |
| 830 String get origin { | 870 String get origin { |
| 831 if (scheme == "" || host == null || host == "") { | 871 if (scheme == "" || _host == null || _host == "") { |
| 832 throw new StateError("Cannot use origin without a scheme: $this"); | 872 throw new StateError("Cannot use origin without a scheme: $this"); |
| 833 } | 873 } |
| 834 if (scheme != "http" && scheme != "https") { | 874 if (scheme != "http" && scheme != "https") { |
| 835 throw new StateError( | 875 throw new StateError( |
| 836 "Origin is only applicable schemes http and https: $this"); | 876 "Origin is only applicable schemes http and https: $this"); |
| 837 } | 877 } |
| 838 if (port == 0) return "$scheme://$host"; | 878 if (port == 0) return "$scheme://$_host"; |
| 839 return "$scheme://$host:$port"; | 879 return "$scheme://$_host:$port"; |
| 840 } | 880 } |
| 841 | 881 |
| 842 /** | 882 /** |
| 843 * Returns the file path from a file URI. | 883 * Returns the file path from a file URI. |
| 844 * | 884 * |
| 845 * The returned path has either Windows or non-Windows | 885 * The returned path has either Windows or non-Windows |
| 846 * semantics. | 886 * semantics. |
| 847 * | 887 * |
| 848 * For non-Windows semantics the slash ("/") is used to separate | 888 * For non-Windows semantics the slash ("/") is used to separate |
| 849 * path segments. | 889 * path segments. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 955 result.write(host); | 995 result.write(host); |
| 956 result.write("\\"); | 996 result.write("\\"); |
| 957 } | 997 } |
| 958 result.writeAll(segments, "\\"); | 998 result.writeAll(segments, "\\"); |
| 959 if (hasDriveLetter && segments.length == 1) result.write("\\"); | 999 if (hasDriveLetter && segments.length == 1) result.write("\\"); |
| 960 return result.toString(); | 1000 return result.toString(); |
| 961 } | 1001 } |
| 962 | 1002 |
| 963 void _writeAuthority(StringSink ss) { | 1003 void _writeAuthority(StringSink ss) { |
| 964 _addIfNonEmpty(ss, userInfo, userInfo, "@"); | 1004 _addIfNonEmpty(ss, userInfo, userInfo, "@"); |
| 965 ss.write(host == null ? "null" : | 1005 ss.write(_host == null ? "null" : _host); |
| 966 host.contains(':') ? '[$host]' : host); | |
| 967 if (port != 0) { | 1006 if (port != 0) { |
| 968 ss.write(":"); | 1007 ss.write(":"); |
| 969 ss.write(port.toString()); | 1008 ss.write(port.toString()); |
| 970 } | 1009 } |
| 971 } | 1010 } |
| 972 | 1011 |
| 973 String toString() { | 1012 String toString() { |
| 974 StringBuffer sb = new StringBuffer(); | 1013 StringBuffer sb = new StringBuffer(); |
| 975 _addIfNonEmpty(sb, scheme, scheme, ':'); | 1014 _addIfNonEmpty(sb, scheme, scheme, ':'); |
| 976 if (hasAuthority || (scheme == "file")) { | 1015 if (hasAuthority || (scheme == "file")) { |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1141 } else if (index != 0) { | 1180 } else if (index != 0) { |
| 1142 var key = element.substring(0, index); | 1181 var key = element.substring(0, index); |
| 1143 var value = element.substring(index + 1); | 1182 var value = element.substring(index + 1); |
| 1144 map[Uri.decodeQueryComponent(key, decode: decode)] = | 1183 map[Uri.decodeQueryComponent(key, decode: decode)] = |
| 1145 decodeQueryComponent(value, decode: decode); | 1184 decodeQueryComponent(value, decode: decode); |
| 1146 } | 1185 } |
| 1147 return map; | 1186 return map; |
| 1148 }); | 1187 }); |
| 1149 } | 1188 } |
| 1150 | 1189 |
| 1190 /** | |
| 1191 * Parse the [host] as a IP version 4 (IPv4) address, returning the address | |
|
floitsch
2013/09/11 13:13:42
an IP
Anders Johnsen
2013/09/11 13:21:44
Done.
| |
| 1192 * as a list of 4 bytes in network byte order (big endian). | |
| 1193 * | |
| 1194 * Throws a [FormatException] if [host] is not a valid IPv4 address | |
| 1195 * representation. | |
| 1196 */ | |
| 1197 static List<int> parseIPv4Address(String host) { | |
| 1198 void error(String msg) { | |
| 1199 throw new FormatException('Illegal IPv4 address, $msg'); | |
| 1200 } | |
| 1201 var bytes = host.split('.'); | |
| 1202 if (bytes.length != 4) { | |
| 1203 error('IPv4 address should contain exactly 4 parts'); | |
| 1204 } | |
| 1205 // TODO: Consider using Uint8List. | |
|
floitsch
2013/09/11 13:13:42
TODO(issue-number) or
TODO(ldap)
Anders Johnsen
2013/09/11 13:21:44
Done.
| |
| 1206 return bytes | |
| 1207 .map((byteString) { | |
| 1208 int byte = int.parse(byteString); | |
| 1209 if (byte < 0 || byte > 255) { | |
| 1210 error('each part must be in the range of `0..255`'); | |
| 1211 } | |
| 1212 return byte; | |
| 1213 }) | |
| 1214 .toList(); | |
| 1215 } | |
| 1216 | |
| 1217 /** | |
| 1218 * Parse the [host] as a IP version 6 (IPv6) address, returning the address | |
|
floitsch
2013/09/11 13:13:42
an IP
Anders Johnsen
2013/09/11 13:21:44
Done.
| |
| 1219 * as a list of 16 bytes in network byte order (big endian). | |
| 1220 * | |
| 1221 * Throws a [FormatException] if [host] is not a valid IPv6 address | |
| 1222 * representation. | |
|
floitsch
2013/09/11 13:13:42
Still missing the examples in the documentation.
Anders Johnsen
2013/09/11 13:21:44
Done.
| |
| 1223 */ | |
| 1224 static List<int> parseIPv6Address(String host) { | |
| 1225 // An IPv6 address consists of exactly 8 parts of 1-4 hex digits, seperated | |
| 1226 // by `:`'s, with the following exceptions: | |
| 1227 // | |
| 1228 // - One (and only one) wildcard (`::`) may be present, representing a fill | |
| 1229 // of 0's. The IPv6 `::` is thus 16 bytes of `0`. | |
| 1230 // - The last two parts may be replaced by an IPv4 address. | |
| 1231 void error(String msg) { | |
| 1232 throw new FormatException('Illegal IPv6 address, $msg'); | |
| 1233 } | |
| 1234 int parseHex(int start, int end) { | |
| 1235 if (end - start > 4) { | |
| 1236 error('an IPv6 part can only contain a maximum of 4 hex digits'); | |
| 1237 } | |
| 1238 int value = int.parse(host.substring(start, end), radix: 16); | |
| 1239 if (value < 0 || value > (1 << 16) - 1) { | |
| 1240 error('each part must be in the range of `0x0..0xFFFF`'); | |
| 1241 } | |
| 1242 return value; | |
| 1243 } | |
| 1244 if (host.length < 2) error('address is too short'); | |
| 1245 List<int> parts = []; | |
| 1246 bool wildcardSeen = false; | |
| 1247 int partStart = 0; | |
| 1248 // Parse all parts, except a potential last one. | |
| 1249 for (int i = 0; i < host.length; i++) { | |
| 1250 if (host.codeUnitAt(i) == _COLON) { | |
| 1251 if (i == 0) { | |
| 1252 // If we see a `:` in the beginning, expect wildcard. | |
| 1253 i++; | |
| 1254 if (host.codeUnitAt(i) != _COLON) { | |
| 1255 error('invalid start colon.'); | |
| 1256 } | |
| 1257 partStart = i; | |
| 1258 } | |
| 1259 if (i == partStart) { | |
| 1260 // Wildcard. We only allow one. | |
| 1261 if (wildcardSeen) { | |
| 1262 error('only one wildcard `::` is allowed'); | |
| 1263 } | |
| 1264 wildcardSeen = true; | |
| 1265 parts.add(-1); | |
| 1266 } else { | |
| 1267 // Found a single colon. Parse [partStart..i] as a hex entry. | |
| 1268 parts.add(parseHex(partStart, i)); | |
| 1269 } | |
| 1270 partStart = i + 1; | |
| 1271 } | |
| 1272 } | |
| 1273 if (parts.length == 0) error('too few parts'); | |
| 1274 bool atEnd = partStart == host.length; | |
| 1275 bool isLastWildcard = parts.last == -1; | |
| 1276 if (atEnd && !isLastWildcard) { | |
| 1277 error('expected a part after last `:`'); | |
| 1278 } | |
| 1279 if (!atEnd) { | |
| 1280 try { | |
| 1281 parts.add(parseHex(partStart, host.length)); | |
| 1282 } catch (e) { | |
| 1283 // Failed to parse the last chunk as hex. Try IPv4. | |
| 1284 try { | |
| 1285 List<int> last = parseIPv4Address(host.substring(partStart)); | |
| 1286 parts.add(last[0] << 8 | last[1]); | |
| 1287 parts.add(last[2] << 8 | last[3]); | |
| 1288 } catch (e) { | |
| 1289 error('invalid end of IPv6 address.'); | |
| 1290 } | |
| 1291 } | |
| 1292 } | |
| 1293 if (wildcardSeen) { | |
| 1294 if (parts.length > 7) { | |
| 1295 error('an address with a wildcard must have less than 7 parts'); | |
| 1296 } | |
| 1297 } else if (parts.length != 8) { | |
| 1298 error('an address without a wildcard must contain exactly 8 parts'); | |
| 1299 } | |
| 1300 // TODO: Consider using Uint8List. | |
|
floitsch
2013/09/11 13:13:42
ditto.
Anders Johnsen
2013/09/11 13:21:44
Done.
| |
| 1301 return parts | |
| 1302 .expand((value) { | |
| 1303 if (value == -1) { | |
| 1304 return new List.filled((9 - parts.length) * 2, 0); | |
| 1305 } else { | |
| 1306 return [(value >> 8) & 0xFF, value & 0xFF]; | |
| 1307 } | |
| 1308 }) | |
| 1309 .toList(); | |
| 1310 } | |
| 1311 | |
| 1151 // Frequently used character codes. | 1312 // Frequently used character codes. |
| 1152 static const int _DOUBLE_QUOTE = 0x22; | 1313 static const int _DOUBLE_QUOTE = 0x22; |
| 1153 static const int _PERCENT = 0x25; | 1314 static const int _PERCENT = 0x25; |
| 1154 static const int _ASTERISK = 0x2A; | 1315 static const int _ASTERISK = 0x2A; |
| 1155 static const int _PLUS = 0x2B; | 1316 static const int _PLUS = 0x2B; |
| 1156 static const int _SLASH = 0x2F; | 1317 static const int _SLASH = 0x2F; |
| 1157 static const int _ZERO = 0x30; | 1318 static const int _ZERO = 0x30; |
| 1158 static const int _NINE = 0x39; | 1319 static const int _NINE = 0x39; |
| 1159 static const int _COLON = 0x3A; | 1320 static const int _COLON = 0x3A; |
| 1160 static const int _LESS = 0x3C; | 1321 static const int _LESS = 0x3C; |
| 1161 static const int _GREATER = 0x3E; | 1322 static const int _GREATER = 0x3E; |
| 1162 static const int _QUESTION = 0x3F; | 1323 static const int _QUESTION = 0x3F; |
| 1163 static const int _AT_SIGN = 0x40; | 1324 static const int _AT_SIGN = 0x40; |
| 1164 static const int _UPPER_CASE_A = 0x41; | 1325 static const int _UPPER_CASE_A = 0x41; |
| 1165 static const int _UPPER_CASE_F = 0x46; | 1326 static const int _UPPER_CASE_F = 0x46; |
| 1166 static const int _UPPER_CASE_Z = 0x5A; | 1327 static const int _UPPER_CASE_Z = 0x5A; |
| 1328 static const int _LEFT_BRACKET = 0x5B; | |
| 1167 static const int _BACKSLASH = 0x5C; | 1329 static const int _BACKSLASH = 0x5C; |
| 1330 static const int _RIGHT_BRACKET = 0x5D; | |
| 1168 static const int _LOWER_CASE_A = 0x61; | 1331 static const int _LOWER_CASE_A = 0x61; |
| 1169 static const int _LOWER_CASE_F = 0x66; | 1332 static const int _LOWER_CASE_F = 0x66; |
| 1170 static const int _LOWER_CASE_Z = 0x7A; | 1333 static const int _LOWER_CASE_Z = 0x7A; |
| 1171 static const int _BAR = 0x7C; | 1334 static const int _BAR = 0x7C; |
| 1172 | 1335 |
| 1173 /** | 1336 /** |
| 1174 * This is the internal implementation of JavaScript's encodeURI function. | 1337 * This is the internal implementation of JavaScript's encodeURI function. |
| 1175 * It encodes all characters in the string [text] except for those | 1338 * It encodes all characters in the string [text] except for those |
| 1176 * that appear in [canonicalTable], and returns the escaped string. | 1339 * that appear in [canonicalTable], and returns the escaped string. |
| 1177 */ | 1340 */ |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1465 void clear() { | 1628 void clear() { |
| 1466 throw new UnsupportedError("Cannot modify an unmodifiable map"); | 1629 throw new UnsupportedError("Cannot modify an unmodifiable map"); |
| 1467 } | 1630 } |
| 1468 void forEach(void f(K key, V value)) => _map.forEach(f); | 1631 void forEach(void f(K key, V value)) => _map.forEach(f); |
| 1469 Iterable<K> get keys => _map.keys; | 1632 Iterable<K> get keys => _map.keys; |
| 1470 Iterable<V> get values => _map.values; | 1633 Iterable<V> get values => _map.values; |
| 1471 int get length => _map.length; | 1634 int get length => _map.length; |
| 1472 bool get isEmpty => _map.isEmpty; | 1635 bool get isEmpty => _map.isEmpty; |
| 1473 bool get isNotEmpty => _map.isNotEmpty; | 1636 bool get isNotEmpty => _map.isNotEmpty; |
| 1474 } | 1637 } |
| OLD | NEW |