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

Unified Diff: sdk/lib/core/uri.dart

Issue 335773003: Revert "Try to retain original structure of URI." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tests/co19/co19-co19.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/core/uri.dart
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
index 9d1466c71b5c9aba0cf4eb72d0238386707cd57d..73a97d80e1c3288aac66beca9735b5bf3d59c4c8 100644
--- a/sdk/lib/core/uri.dart
+++ b/sdk/lib/core/uri.dart
@@ -16,14 +16,8 @@ part of dart.core;
* [libtour]: http://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html
*/
class Uri {
- // The host name of the URI.
- // Set to `null` if there is no authority in a URI.
final String _host;
- // The port. Set to null if there is no port. Normalized to null if
- // the port is the default port for the scheme.
- // Set to the value of the default port if an empty port was supplied.
int _port;
- // The path. Always non-null.
String _path;
/**
@@ -31,8 +25,6 @@ class Uri {
*
* Returns the empty string if there is no scheme component.
*/
- // We represent the missing scheme as an empty string.
- // A valid scheme cannot be empty.
final String scheme;
/**
@@ -51,20 +43,12 @@ class Uri {
}
/**
- * The user-info part of the authority.
- *
- * Does not distinguish between an empty user-info and an absent one.
- * The value is always non-null.
- */
- final String _userInfo;
-
- /**
* Returns the user info part of the authority component.
*
* Returns the empty string if there is no user info in the
* authority component.
*/
- String get userInfo => _userInfo;
+ final String userInfo;
/**
* Returns the host part of the authority component.
@@ -76,8 +60,7 @@ class Uri {
* removed.
*/
String get host {
- if (_host == null) return "";
- if (_host.startsWith('[')) {
+ if (_host != null && _host.startsWith('[')) {
return _host.substring(1, _host.length - 1);
}
return _host;
@@ -86,21 +69,16 @@ class Uri {
/**
* Returns the port part of the authority component.
*
- * Returns the defualt port if there is no port number in the authority
- * component. That's 80 for http, 443 for https, and 0 for everything else.
+ * Returns 0 if there is no port in the authority component.
*/
int get port {
- if (_port == null) return _defaultPort(scheme);
+ if (_port == 0) {
+ if (scheme == "http") return 80;
+ if (scheme == "https") return 443;
+ }
return _port;
}
- // The default port for the scheme of this Uri..
- static int _defaultPort(String scheme) {
- if (scheme == "http") return 80;
- if (scheme == "https") return 443;
- return 0;
- }
-
/**
* Returns the path component.
*
@@ -111,19 +89,13 @@ class Uri {
*/
String get path => _path;
- // The query content, or null if there is no query.
- final String _query;
-
/**
* Returns the query component. The returned query is encoded. To get
* direct access to the decoded query use [queryParameters].
*
* Returns the empty string if there is no query component.
*/
- String get query => (_query == null) ? "" : _query;
-
- // The fragment content, or null if there is no fragment.
- final String _fragment;
+ final String query;
/**
* Returns the fragment identifier component.
@@ -131,7 +103,7 @@ class Uri {
* Returns the empty string if there is no fragment identifier
* component.
*/
- String get fragment => (_fragment == null) ? "" : _fragment;
+ final String fragment;
/**
* Cache the computed return value of [pathSegements].
@@ -210,12 +182,12 @@ class Uri {
const int EOI = -1;
String scheme = "";
+ String path;
String userinfo = "";
- String host = null;
- int port = null;
- String path = null;
- String query = null;
- String fragment = null;
+ String host = "";
+ int port = 0;
+ String query = "";
+ String fragment = "";
int index = 0;
int pathStart = 0;
@@ -262,16 +234,13 @@ class Uri {
hostStart = lastAt + 1;
}
if (lastColon >= 0) {
- int portNumber;
- if (lastColon + 1 < index) {
- portNumber = 0;
- for (int i = lastColon + 1; i < index; i++) {
- int digit = uri.codeUnitAt(i);
- if (_ZERO > digit || _NINE < digit) {
- _fail(uri, i, "Invalid port number");
- }
- portNumber = portNumber * 10 + (digit - _ZERO);
+ int portNumber = 0;
+ for (int i = lastColon + 1; i < index; i++) {
+ int digit = uri.codeUnitAt(i);
+ if (_ZERO > digit || _NINE < digit) {
+ _fail(uri, i, "Invalid port number");
}
+ portNumber = portNumber * 10 + (digit - _ZERO);
}
port = _makePort(portNumber, scheme);
hostEnd = lastColon;
@@ -371,7 +340,7 @@ class Uri {
}
assert(state == NOT_IN_PATH);
- bool ensureLeadingSlash = (host != null || scheme == "file");
+ bool ensureLeadingSlash = (host != "" || scheme == "file");
path = _makePath(uri, pathStart, index, null, ensureLeadingSlash);
if (char == _QUESTION) {
@@ -428,27 +397,27 @@ class Uri {
/// Internal non-verifying constructor. Only call with validated arguments.
Uri._internal(this.scheme,
- this._userInfo,
+ this.userInfo,
this._host,
this._port,
this._path,
- this._query,
- this._fragment);
+ this.query,
+ this.fragment);
/**
* Creates a new URI from its components.
*
* Each component is set through a named argument. Any number of
- * components can be provided. The [path] and [query] components can be set
- * using either of two different named arguments.
+ * components can be provided. The default value for the components
+ * not provided is the empry string, except for [port] which has a
+ * default value of 0. The [path] and [query] components can be set
+ * using two different named arguments.
*
* The scheme component is set through [scheme]. The scheme is
- * normalized to all lowercase letters. If the scheme is omitted or empty,
- * the URI will not have a scheme part.
+ * normalized to all lowercase letters.
*
* The user info part of the authority component is set through
- * [userInfo]. It defaults to the empty string, which will be omitted
- * from the string representation of the URI.
+ * [userInfo].
*
* The host part of the authority component is set through
* [host]. The host can either be a hostname, an IPv4 address or an
@@ -457,22 +426,14 @@ class Uri {
* The host is normalized to all lowercase letters.
*
* The port part of the authority component is set through
- * [port].
- * If [port] is omitted or `null`, it implies the default port for
- * the URI's scheme, and is equivalent to passing that port explicitly.
- * The recognized schemes, and their default ports, are "http" (80) and
- * "https" (443). All other schemes are considered as having zero as the
- * default port.
- *
- * If any of `userInfo`, `host` or `port` are provided,
- * the URI will have an autority according to [hasAuthority].
+ * [port]. The port is normalized for scheme http and https where
+ * port 80 and port 443 respectively is set.
*
* The path component is set through either [path] or
- * [pathSegments]. When [path] is used, it should be a valid URI path,
- * but invalid characters, except the general delimiters ':/@[]?#',
- * will be escaped if necessary.
- * When [pathSegments] is used, each of the provided segments
- * is first percent-encoded and then joined using the forward slash
+ * [pathSegments]. When [path] is used, the provided string is
+ * expected to be fully percent-encoded, and is used in its literal
+ * form. When [pathSegments] is used, each of the provided segments
+ * is percent-encoded and joined using the forward slash
* separator. The percent-encoding of the path segments encodes all
* characters except for the unreserved characters and the following
* list of characters: `!$&'()*+,;=:@`. If the other components
@@ -480,43 +441,32 @@ class Uri {
* not already there.
*
* The query component is set through either [query] or
- * [queryParameters]. When [query] is used the provided string should
- * be a valid URI query, but invalid characters other than general delimiters,
- * will be escaped if necessary.
- * When [queryParameters] is used the query is built from the
+ * [queryParameters]. When [query] is used the provided string is
+ * expected to be fully percent-encoded and is used in its literal
+ * form. When [queryParameters] is used the query is built from the
* provided map. Each key and value in the map is percent-encoded
* and joined using equal and ampersand characters. The
* percent-encoding of the keys and values encodes all characters
* except for the unreserved characters.
- * If both `query` and `queryParameters` are omitted or `null`, the
- * URI will have no query part.
*
* The fragment component is set through [fragment].
- * It should be a valid URI fragment, but invalid characters other than
- * general delimiters, will be escaped if necessary.
- * If `fragment` is omitted or `null`, the URI will have no fragment part.
*/
- factory Uri({String scheme : "",
- String userInfo : "",
- String host,
- int port,
- String path,
- Iterable<String> pathSegments,
- String query,
- Map<String, String> queryParameters,
- fragment}) {
+ factory Uri({String scheme,
+ String userInfo: "",
+ String host: "",
+ port: 0,
+ String path,
+ Iterable<String> pathSegments,
+ String query,
+ Map<String, String> queryParameters,
+ fragment: ""}) {
scheme = _makeScheme(scheme, _stringOrNullLength(scheme));
userInfo = _makeUserInfo(userInfo, 0, _stringOrNullLength(userInfo));
host = _makeHost(host, 0, _stringOrNullLength(host), false);
query = _makeQuery(query, 0, _stringOrNullLength(query), queryParameters);
fragment = _makeFragment(fragment, 0, _stringOrNullLength(fragment));
port = _makePort(port, scheme);
- bool isFile = (scheme == "file");
- if (host == null &&
- (userInfo.isNotEmpty || port != null || isFile)) {
- host = "";
- }
- bool ensureLeadingSlash = (host != null || isFile);
+ bool ensureLeadingSlash = (host != "" || scheme == "file");
path = _makePath(path, 0, _stringOrNullLength(path), pathSegments,
ensureLeadingSlash);
@@ -546,9 +496,7 @@ class Uri {
* The `scheme` is always set to `http`.
*
* The `userInfo`, `host` and `port` components are set from the
- * [authority] argument. If `authority` is `null` or empty,
- * the created `Uri` will have no authority, and will not be directly usable
- * as an HTTP URL, which must have a non-empty host.
+ * [authority] argument.
*
* The `path` component is set from the [unencodedPath]
* argument. The path passed must not be encoded as this constructor
@@ -579,51 +527,50 @@ class Uri {
String authority,
String unencodedPath,
Map<String, String> queryParameters) {
- var userInfo = null;
- var host = null;
- var port = null;
-
- if (authority != null && authority.isNotEmpty) {
- var hostStart = 0;
- // Split off the user info.
- bool hasUserInfo = false;
- for (int i = 0; i < authority.length; i++) {
- if (authority.codeUnitAt(i) == _AT_SIGN) {
- hasUserInfo = true;
- userInfo = authority.substring(0, i);
- hostStart = i + 1;
- break;
- }
- }
- var hostEnd = hostStart;
- if (hostStart < authority.length &&
- authority.codeUnitAt(hostStart) == _LEFT_BRACKET) {
- // IPv6 host.
- for (; hostEnd < authority.length; hostEnd++) {
- if (authority.codeUnitAt(hostEnd) == _RIGHT_BRACKET) break;
- }
- if (hostEnd == authority.length) {
- throw new FormatException("Invalid IPv6 host entry.");
- }
- parseIPv6Address(authority, hostStart + 1, hostEnd);
- hostEnd++; // Skip the closing bracket.
- if (hostEnd != authority.length &&
- authority.codeUnitAt(hostEnd) != _COLON) {
- throw new FormatException("Invalid end of authority");
- }
+ var userInfo = "";
+ var host = "";
+ var port = 0;
+
+ var hostStart = 0;
+ // Split off the user info.
+ bool hasUserInfo = false;
+ for (int i = 0; i < authority.length; i++) {
+ if (authority.codeUnitAt(i) == _AT_SIGN) {
+ hasUserInfo = true;
+ userInfo = authority.substring(0, i);
+ hostStart = i + 1;
+ break;
}
- // Split host and port.
- bool hasPort = false;
+ }
+ var hostEnd = hostStart;
+ if (hostStart < authority.length &&
+ authority.codeUnitAt(hostStart) == _LEFT_BRACKET) {
+ // IPv6 host.
for (; hostEnd < authority.length; hostEnd++) {
- if (authority.codeUnitAt(hostEnd) == _COLON) {
- var portString = authority.substring(hostEnd + 1);
- // We allow the empty port - falling back to initial value.
- if (portString.isNotEmpty) port = int.parse(portString);
- break;
- }
+ if (authority.codeUnitAt(hostEnd) == _RIGHT_BRACKET) break;
+ }
+ if (hostEnd == authority.length) {
+ throw new FormatException("Invalid IPv6 host entry.");
+ }
+ parseIPv6Address(authority, hostStart + 1, hostEnd);
+ hostEnd++; // Skip the closing bracket.
+ if (hostEnd != authority.length &&
+ authority.codeUnitAt(hostEnd) != _COLON) {
+ throw new FormatException("Invalid end of authority");
+ }
+ }
+ // Split host and port.
+ bool hasPort = false;
+ for (; hostEnd < authority.length; hostEnd++) {
+ if (authority.codeUnitAt(hostEnd) == _COLON) {
+ var portString = authority.substring(hostEnd + 1);
+ // We allow the empty port - falling back to initial value.
+ if (portString.isNotEmpty) port = int.parse(portString);
+ break;
}
- host = authority.substring(hostStart, hostEnd);
}
+ host = authority.substring(hostStart, hostEnd);
+
return new Uri(scheme: scheme,
userInfo: userInfo,
host: host,
@@ -774,7 +721,7 @@ class Uri {
static _makeFileUri(String path) {
String sep = "/";
- if (path.startsWith(sep)) {
+ if (path.length > 0 && path[0] == sep) {
// Absolute file:// URI.
return new Uri(scheme: "file", pathSegments: path.split(sep));
} else {
@@ -883,7 +830,12 @@ class Uri {
static int _makePort(int port, String scheme) {
// Perform scheme specific normalization.
- if (port != null && port == _defaultPort(scheme)) return null;
+ if (port == 80 && scheme == "http") {
+ return 0;
+ }
+ if (port == 443 && scheme == "https") {
+ return 0;
+ }
return port;
}
@@ -900,6 +852,7 @@ class Uri {
*/
static String _makeHost(String host, int start, int end, bool strictIPv6) {
// TODO(lrn): Should we normalize IPv6 addresses according to RFC 5952?
+
if (host == null) return null;
if (start == end) return "";
// Host is an IPv6 address if it starts with '[' or contains a colon.
@@ -1032,7 +985,7 @@ class Uri {
}
static String _makeUserInfo(String userInfo, int start, int end) {
- if (userInfo == null) return "";
+ if (userInfo == null) return "null";
return _normalize(userInfo, start, end, _userinfoTable);
}
@@ -1057,7 +1010,7 @@ class Uri {
static String _makeQuery(String query, int start, int end,
Map<String, String> queryParameters) {
- if (query == null && queryParameters == null) return null;
+ if (query == null && queryParameters == null) return "";
if (query != null && queryParameters != null) {
throw new ArgumentError('Both query and queryParameters specified');
}
@@ -1080,7 +1033,7 @@ class Uri {
}
static String _makeFragment(String fragment, int start, int end) {
- if (fragment == null) return null;
+ if (fragment == null) return "";
return _normalize(fragment, start, end, _queryCharTable);
}
@@ -1325,81 +1278,55 @@ class Uri {
int targetPort;
String targetPath;
String targetQuery;
- if (reference.scheme.isNotEmpty) {
+ if (reference.scheme != "") {
targetScheme = reference.scheme;
- if (reference.hasAuthority) {
- targetUserInfo = reference.userInfo;
- targetHost = reference.host;
- targetPort = reference.hasPort ? reference.port : null;
- }
+ targetUserInfo = reference.userInfo;
+ targetHost = reference.host;
+ targetPort = reference.port;
targetPath = _removeDotSegments(reference.path);
- if (reference.hasQuery) {
- targetQuery = reference.query;
- }
+ targetQuery = reference.query;
} else {
- targetScheme = this.scheme;
if (reference.hasAuthority) {
targetUserInfo = reference.userInfo;
targetHost = reference.host;
- targetPort = _makePort(reference.hasPort ? reference.port : null,
- targetScheme);
+ targetPort = reference.port;
targetPath = _removeDotSegments(reference.path);
- if (reference.hasQuery) targetQuery = reference.query;
+ targetQuery = reference.query;
} else {
if (reference.path == "") {
- targetPath = this._path;
- if (reference.hasQuery) {
+ targetPath = this.path;
+ if (reference.query != "") {
targetQuery = reference.query;
} else {
- targetQuery = this._query;
+ targetQuery = this.query;
}
} else {
if (reference.path.startsWith("/")) {
targetPath = _removeDotSegments(reference.path);
} else {
- targetPath = _removeDotSegments(_merge(this._path, reference.path));
+ targetPath = _removeDotSegments(_merge(this.path, reference.path));
}
- if (reference.hasQuery) targetQuery = reference.query;
+ targetQuery = reference.query;
}
- targetUserInfo = this._userInfo;
- targetHost = this._host;
- targetPort = this._port;
+ targetUserInfo = this.userInfo;
+ targetHost = this.host;
+ targetPort = this.port;
}
+ targetScheme = this.scheme;
}
- String fragment = reference.hasFragment ? reference.fragment : null;
- return new Uri._internal(targetScheme,
- targetUserInfo,
- targetHost,
- targetPort,
- targetPath,
- targetQuery,
- fragment);
+ return new Uri(scheme: targetScheme,
+ userInfo: targetUserInfo,
+ host: targetHost,
+ port: targetPort,
+ path: targetPath,
+ query: targetQuery,
+ fragment: reference.fragment);
}
/**
* Returns whether the URI has an [authority] component.
*/
- bool get hasAuthority => _host != null;
-
- /**
- * Returns whether the URI has an explicit port.
- *
- * If the port number is the default port number
- * (zero for unrecognized schemes, with http (80) and https (443) being
- * recognized),
- * then the port is made implicit and omitted from the URI.
- */
- bool get hasPort => _port != null;
-
- /**
- * Returns whether the URI has a query part.
- */
- bool get hasQuery => _query != null;
-
- /**
- * Returns whether the URI has a fragment part.
- */
- bool get hasFragment => _fragment != null;
+ bool get hasAuthority => host != "";
/**
* Returns the origin of the URI in the form scheme://host:port for the
@@ -1417,7 +1344,7 @@ class Uri {
throw new StateError(
"Origin is only applicable schemes http and https: $this");
}
- if (_port == null) return "$scheme://$_host";
+ if (_port == 0) return "$scheme://$_host";
return "$scheme://$_host:$_port";
}
@@ -1544,14 +1471,11 @@ class Uri {
}
void _writeAuthority(StringSink ss) {
- if (_userInfo.isNotEmpty) {
- ss.write(_userInfo);
- ss.write("@");
- }
- if (_host != null) ss.write(_host);
- if (_port != null) {
+ _addIfNonEmpty(ss, userInfo, userInfo, "@");
+ ss.write(_host == null ? "null" : _host);
+ if (_port != 0) {
ss.write(":");
- ss.write(_port);
+ ss.write(_port.toString());
}
}
@@ -1565,8 +1489,8 @@ class Uri {
_writeAuthority(sb);
}
sb.write(path);
- if (_query != null) { sb..write("?")..write(_query); }
- if (_fragment != null) { sb..write("#")..write(_fragment); }
+ _addIfNonEmpty(sb, query, "?", query);
+ _addIfNonEmpty(sb, fragment, "#", fragment);
return sb.toString();
}
« no previous file with comments | « no previous file | tests/co19/co19-co19.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698