refactor(*): faster check for a string starting with a substring
Thanks to @spamdaemon for the original PR to make this improvement.
In naive tests on Chrome I got the following results:
```
Matches Misses
indexOf 33ms 1494ms
lastIndexOf 11ms 11ms
```
Closes #3711
This commit is contained in:
+20
-17
@@ -48,17 +48,20 @@ function parseAppUrl(relativeUrl, locationObj) {
|
||||
}
|
||||
}
|
||||
|
||||
function startsWith(haystack, needle) {
|
||||
return haystack.lastIndexOf(needle, 0) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} begin
|
||||
* @param {string} whole
|
||||
* @returns {string} returns text from whole after begin or undefined if it does not begin with
|
||||
* expected string.
|
||||
* @param {string} base
|
||||
* @param {string} url
|
||||
* @returns {string} returns text from `url` after `base` or `undefined` if it does not begin with
|
||||
* the expected string.
|
||||
*/
|
||||
function beginsWith(begin, whole) {
|
||||
if (whole.indexOf(begin) === 0) {
|
||||
return whole.substr(begin.length);
|
||||
function stripBaseUrl(base, url) {
|
||||
if (startsWith(url, base)) {
|
||||
return url.substr(base.length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +107,7 @@ function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {
|
||||
* @private
|
||||
*/
|
||||
this.$$parse = function(url) {
|
||||
var pathUrl = beginsWith(appBaseNoFile, url);
|
||||
var pathUrl = stripBaseUrl(appBaseNoFile, url);
|
||||
if (!isString(pathUrl)) {
|
||||
throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
|
||||
appBaseNoFile);
|
||||
@@ -141,14 +144,14 @@ function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {
|
||||
var appUrl, prevAppUrl;
|
||||
var rewrittenUrl;
|
||||
|
||||
if (isDefined(appUrl = beginsWith(appBase, url))) {
|
||||
if (isDefined(appUrl = stripBaseUrl(appBase, url))) {
|
||||
prevAppUrl = appUrl;
|
||||
if (isDefined(appUrl = beginsWith(basePrefix, appUrl))) {
|
||||
rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
|
||||
if (isDefined(appUrl = stripBaseUrl(basePrefix, appUrl))) {
|
||||
rewrittenUrl = appBaseNoFile + (stripBaseUrl('/', appUrl) || appUrl);
|
||||
} else {
|
||||
rewrittenUrl = appBase + prevAppUrl;
|
||||
}
|
||||
} else if (isDefined(appUrl = beginsWith(appBaseNoFile, url))) {
|
||||
} else if (isDefined(appUrl = stripBaseUrl(appBaseNoFile, url))) {
|
||||
rewrittenUrl = appBaseNoFile + appUrl;
|
||||
} else if (appBaseNoFile === url + '/') {
|
||||
rewrittenUrl = appBaseNoFile;
|
||||
@@ -182,14 +185,14 @@ function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) {
|
||||
* @private
|
||||
*/
|
||||
this.$$parse = function(url) {
|
||||
var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
|
||||
var withoutBaseUrl = stripBaseUrl(appBase, url) || stripBaseUrl(appBaseNoFile, url);
|
||||
var withoutHashUrl;
|
||||
|
||||
if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') {
|
||||
|
||||
// The rest of the url starts with a hash so we have
|
||||
// got either a hashbang path or a plain hash fragment
|
||||
withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);
|
||||
withoutHashUrl = stripBaseUrl(hashPrefix, withoutBaseUrl);
|
||||
if (isUndefined(withoutHashUrl)) {
|
||||
// There was no hashbang prefix so we just have a hash fragment
|
||||
withoutHashUrl = withoutBaseUrl;
|
||||
@@ -237,7 +240,7 @@ function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) {
|
||||
var firstPathSegmentMatch;
|
||||
|
||||
//Get the relative path from the input URL.
|
||||
if (url.indexOf(base) === 0) {
|
||||
if (startsWith(url, base)) {
|
||||
url = url.replace(base, '');
|
||||
}
|
||||
|
||||
@@ -300,7 +303,7 @@ function LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) {
|
||||
|
||||
if (appBase === stripHash(url)) {
|
||||
rewrittenUrl = url;
|
||||
} else if ((appUrl = beginsWith(appBaseNoFile, url))) {
|
||||
} else if ((appUrl = stripBaseUrl(appBaseNoFile, url))) {
|
||||
rewrittenUrl = appBase + hashPrefix + appUrl;
|
||||
} else if (appBaseNoFile === url + '/') {
|
||||
rewrittenUrl = appBaseNoFile;
|
||||
@@ -909,7 +912,7 @@ function $LocationProvider() {
|
||||
// update $location when $browser url changes
|
||||
$browser.onUrlChange(function(newUrl, newState) {
|
||||
|
||||
if (isUndefined(beginsWith(appBaseNoFile, newUrl))) {
|
||||
if (isUndefined(stripBaseUrl(appBaseNoFile, newUrl))) {
|
||||
// If we are navigating outside of the app then force a reload
|
||||
$window.location.href = newUrl;
|
||||
return;
|
||||
|
||||
@@ -489,7 +489,7 @@ function stripCustomNsAttrs(node) {
|
||||
for (var i = 0, l = attrs.length; i < l; i++) {
|
||||
var attrNode = attrs[i];
|
||||
var attrName = attrNode.name.toLowerCase();
|
||||
if (attrName === 'xmlns:ns1' || attrName.indexOf('ns1:') === 0) {
|
||||
if (attrName === 'xmlns:ns1' || attrName.lastIndexOf('ns1:', 0) === 0) {
|
||||
node.removeAttributeNode(attrNode);
|
||||
i--;
|
||||
l--;
|
||||
|
||||
Reference in New Issue
Block a user