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

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

Issue 2374253004: Fix bug in _SimpleUri.resolve. (Closed)
Patch Set: Address comments. Created 4 years, 3 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/corelib/uri_test.dart » ('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 d7f911bfa55d98e782e3be82b6730191046c91b2..847521ac48b1f52cf89d2a3a09bbbed59e54a671 100644
--- a/sdk/lib/core/uri.dart
+++ b/sdk/lib/core/uri.dart
@@ -4323,10 +4323,6 @@ class _SimpleUri implements Uri {
base._schemeCache);
}
// Merge paths.
- if (base._uri.startsWith("../", base._pathStart)) {
- // Complex rare case, go slow.
- return _toNonSimple().resolveUri(ref);
- }
// The RFC 3986 algorithm merges the base path without its final segment
// (anything after the final "/", or everything if the base path doesn't
@@ -4341,39 +4337,53 @@ class _SimpleUri implements Uri {
String refUri = ref._uri;
int baseStart = base._pathStart;
int baseEnd = base._queryStart;
+ while (baseUri.startsWith("../", baseStart)) baseStart += 3;
int refStart = ref._pathStart;
int refEnd = ref._queryStart;
- int backCount = 1;
-
- int slashCount = 0;
- // Count leading ".." segments in reference path.
+ /// Count of leading ".." segments in reference path.
+ /// The count is decremented when the segment is matched with a
+ /// segment of the base path, and both are then omitted from the result.
+ int backCount = 0;
+ /// Count "../" segments and advance `refStart` to after the segments.
while (refStart + 3 <= refEnd && refUri.startsWith("../", refStart)) {
refStart += 3;
backCount += 1;
}
// Extra slash inserted between base and reference path parts if
- // the base path contains any slashes.
+ // the base path contains any slashes, or empty string if none.
// (We could use a slash from the base path in most cases, but not if
// we remove the entire base path).
String insert = "";
+
+ /// Remove segments from the base path.
+ /// Start with the segment trailing the last slash,
+ /// then remove segments for each leading "../" segment
+ /// from the reference path, or as many of them as are available.
while (baseEnd > baseStart) {
baseEnd--;
int char = baseUri.codeUnitAt(baseEnd);
if (char == _SLASH) {
insert = "/";
- backCount--;
if (backCount == 0) break;
+ backCount--;
}
}
- // If the base URI has no scheme or authority (`_pathStart == 0`)
- // and a relative path, and we reached the beginning of the path,
- // we have a special case.
- if (baseEnd == 0 && !base.hasAbsolutePath) {
- // Non-RFC 3986 behavior when resolving a purely relative path on top of
- // another relative path: Don't make the result absolute.
+
+ if (baseEnd == baseStart && !base.hasScheme && !base.hasAbsolutePath) {
+ // If the base is *just* a relative path (no scheme or authority),
+ // then merging with another relative path doesn't follow the
+ // RFC-3986 behavior.
+ // Don't need to check `base.hasAuthority` since the base path is
+ // non-empty - if there is an authority, a non-empty path is absolute.
+
+ // We reached the start of the base path, and want to stay relative,
+ // so don't insert a slash.
insert = "";
+ // If we reached the start of the base path with more "../" left over
+ // in the reference path, include those segments in the result.
+ refStart -= backCount * 3;
}
var delta = baseEnd - refStart + insert.length;
« no previous file with comments | « no previous file | tests/corelib/uri_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698