diff --git a/src/ng/location.js b/src/ng/location.js index f06a5f811a7d..402db3cf04d5 100644 --- a/src/ng/location.js +++ b/src/ng/location.js @@ -179,7 +179,47 @@ function LocationHashbangUrl(appBase, hashPrefix) { hashPrefix); } parseAppUrl(withoutHashUrl, this, appBase); + + this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase); + this.$$compose(); + + /* + * In Windows, on an anchor node on documents loaded from + * the filesystem, the browser will return a pathname + * prefixed with the drive name ('/C:/path') when a + * pathname without a drive is set: + * * a.setAttribute('href', '/foo') + * * a.pathname === '/C:/foo' //true + * + * Inside of Angular, we're always using pathnames that + * do not include drive names for routing. + */ + function removeWindowsDriveName (path, url, base) { + /* + Matches paths for file protocol on windows, + such as /C:/foo/bar, and captures only /foo/bar. + */ + var windowsFilePathExp = /^\/?.*?:(\/.*)/; + + var firstPathSegmentMatch; + + //Get the relative path from the input URL. + if (url.indexOf(base) === 0) { + url = url.replace(base, ''); + } + + /* + * The input URL intentionally contains a + * first path segment that ends with a colon. + */ + if (windowsFilePathExp.exec(url)) { + return path; + } + + firstPathSegmentMatch = windowsFilePathExp.exec(path); + return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path; + } }; /** diff --git a/src/ng/urlUtils.js b/src/ng/urlUtils.js index cba8981cbd27..3169248fc672 100644 --- a/src/ng/urlUtils.js +++ b/src/ng/urlUtils.js @@ -7,11 +7,6 @@ // exactly the behavior needed here. There is little value is mocking these out for this // service. var urlParsingNode = document.createElement("a"); -/* -Matches paths for file protocol on windows, -such as /C:/foo/bar, and captures only /foo/bar. -*/ -var windowsFilePathExp = /^\/?.*?:(\/.*)/; var originUrl = urlResolve(window.location.href, true); @@ -68,8 +63,7 @@ var originUrl = urlResolve(window.location.href, true); * */ function urlResolve(url, base) { - var href = url, - pathname; + var href = url; if (msie) { // Normalize before parse. Refer Implementation Notes on why this is @@ -80,21 +74,6 @@ function urlResolve(url, base) { urlParsingNode.setAttribute('href', href); - /* - * In Windows, on an anchor node on documents loaded from - * the filesystem, the browser will return a pathname - * prefixed with the drive name ('/C:/path') when a - * pathname without a drive is set: - * * a.setAttribute('href', '/foo') - * * a.pathname === '/C:/foo' //true - * - * Inside of Angular, we're always using pathnames that - * do not include drive names for routing. - */ - - pathname = removeWindowsDriveName(urlParsingNode.pathname, url, base); - pathname = (pathname.charAt(0) === '/') ? pathname : '/' + pathname; - // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils return { href: urlParsingNode.href, @@ -104,11 +83,12 @@ function urlResolve(url, base) { hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', hostname: urlParsingNode.hostname, port: urlParsingNode.port, - pathname: pathname + pathname: (urlParsingNode.pathname.charAt(0) === '/') + ? urlParsingNode.pathname + : '/' + urlParsingNode.pathname }; } - /** * Parse a request URL and determine whether this is a same-origin request as the application document. * @@ -121,23 +101,3 @@ function urlIsSameOrigin(requestUrl) { return (parsed.protocol === originUrl.protocol && parsed.host === originUrl.host); } - -function removeWindowsDriveName (path, url, base) { - var firstPathSegmentMatch; - - //Get the relative path from the input URL. - if (url.indexOf(base) === 0) { - url = url.replace(base, ''); - } - - /* - * The input URL intentionally contains a - * first path segment that ends with a colon. - */ - if (windowsFilePathExp.exec(url)) { - return path; - } - - firstPathSegmentMatch = windowsFilePathExp.exec(path); - return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path; -} \ No newline at end of file diff --git a/test/ng/locationSpec.js b/test/ng/locationSpec.js index ad565772f8bb..b9dd17fa505d 100644 --- a/test/ng/locationSpec.js +++ b/test/ng/locationSpec.js @@ -38,7 +38,6 @@ describe('$location', function() { if ($sniffer.msie) return; //reset urlParsingNode urlParsingNode = urlParsingNodePlaceholder; - expect(urlParsingNode.pathname).not.toBe('/C:/foo'); })); @@ -324,7 +323,7 @@ describe('$location', function() { }); - it('should parse hashband url into path and search', function() { + it('should parse hashbang url into path and search', function() { expect(url.protocol()).toBe('http'); expect(url.host()).toBe('www.server.org'); expect(url.port()).toBe(1234); diff --git a/test/ng/urlUtilsSpec.js b/test/ng/urlUtilsSpec.js index 18675ed812a6..543ff3fb6b41 100644 --- a/test/ng/urlUtilsSpec.js +++ b/test/ng/urlUtilsSpec.js @@ -1,7 +1,7 @@ 'use strict'; describe('urlUtils', function() { - describe('parse', function() { + describe('urlResolve', function() { it('should normalize a relative url', function () { expect(urlResolve("foo").href).toMatch(/^https?:\/\/[^/]+\/foo$/); }); @@ -14,6 +14,13 @@ describe('urlUtils', function() { expect(parsed.hostname).not.toBe(""); expect(parsed.pathname).not.toBe(""); }); + + + it('should return pathname as / if empty path provided', function () { + //IE counts / as empty, necessary to use / so that pathname is not context.html + var parsed = urlResolve('/'); + expect(parsed.pathname).toBe('/'); + }) }); describe('isSameOrigin', function() {