aboutsummaryrefslogtreecommitdiff
path: root/contexts/data/lib/closure-library/closure/goog/uri/uri.js
diff options
context:
space:
mode:
Diffstat (limited to 'contexts/data/lib/closure-library/closure/goog/uri/uri.js')
-rw-r--r--contexts/data/lib/closure-library/closure/goog/uri/uri.js379
1 files changed, 136 insertions, 243 deletions
diff --git a/contexts/data/lib/closure-library/closure/goog/uri/uri.js b/contexts/data/lib/closure-library/closure/goog/uri/uri.js
index e26cc1d..c486935 100644
--- a/contexts/data/lib/closure-library/closure/goog/uri/uri.js
+++ b/contexts/data/lib/closure-library/closure/goog/uri/uri.js
@@ -66,8 +66,8 @@ goog.Uri = function(opt_uri, opt_ignoreCase) {
// Parse in the uri string
var m;
if (opt_uri instanceof goog.Uri) {
- this.setIgnoreCase(opt_ignoreCase == null ?
- opt_uri.getIgnoreCase() : opt_ignoreCase);
+ this.ignoreCase_ = goog.isDef(opt_ignoreCase) ?
+ opt_ignoreCase : opt_uri.getIgnoreCase();
this.setScheme(opt_uri.getScheme());
this.setUserInfo(opt_uri.getUserInfo());
this.setDomain(opt_uri.getDomain());
@@ -76,8 +76,9 @@ goog.Uri = function(opt_uri, opt_ignoreCase) {
this.setQueryData(opt_uri.getQueryData().clone());
this.setFragment(opt_uri.getFragment());
} else if (opt_uri && (m = goog.uri.utils.split(String(opt_uri)))) {
+ this.ignoreCase_ = !!opt_ignoreCase;
+
// Set the parts -- decoding as we do so.
- this.setIgnoreCase(!!opt_ignoreCase);
// COMPATABILITY NOTE - In IE, unmatched fields may be empty strings,
// whereas in other browsers they will be undefined.
this.setScheme(m[goog.uri.utils.ComponentIndex.SCHEME] || '', true);
@@ -85,19 +86,33 @@ goog.Uri = function(opt_uri, opt_ignoreCase) {
this.setDomain(m[goog.uri.utils.ComponentIndex.DOMAIN] || '', true);
this.setPort(m[goog.uri.utils.ComponentIndex.PORT]);
this.setPath(m[goog.uri.utils.ComponentIndex.PATH] || '', true);
-
- this.setQuery(m[goog.uri.utils.ComponentIndex.QUERY_DATA] || '', true);
-
+ this.setQueryData(m[goog.uri.utils.ComponentIndex.QUERY_DATA] || '', true);
this.setFragment(m[goog.uri.utils.ComponentIndex.FRAGMENT] || '', true);
} else {
- this.setIgnoreCase(!!opt_ignoreCase);
- this.queryData_ = new goog.Uri.QueryData(null, this, this.ignoreCase_);
+ this.ignoreCase_ = !!opt_ignoreCase;
+ this.queryData_ = new goog.Uri.QueryData(null, null, this.ignoreCase_);
}
};
/**
+ * If true, we preserve the type of query parameters set programmatically.
+ *
+ * This means that if you set a parameter to a boolean, and then call
+ * getParameterValue, you will get a boolean back.
+ *
+ * If false, we will coerce parameters to strings, just as they would
+ * appear in real URIs.
+ *
+ * TODO(nicksantos): Remove this once people have time to fix all tests.
+ *
+ * @type {boolean}
+ */
+goog.Uri.preserveParameterTypesCompatibilityFlag = false;
+
+
+/**
* Parameter name added to stop caching.
* @type {string}
*/
@@ -178,55 +193,58 @@ goog.Uri.prototype.ignoreCase_ = false;
/**
* @return {string} The string form of the url.
+ * @override
*/
goog.Uri.prototype.toString = function() {
- if (this.cachedToString_) {
- return this.cachedToString_;
- }
-
var out = [];
- if (this.scheme_) {
+ var scheme = this.getScheme();
+ if (scheme) {
out.push(goog.Uri.encodeSpecialChars_(
- this.scheme_, goog.Uri.reDisallowedInSchemeOrUserInfo_), ':');
+ scheme, goog.Uri.reDisallowedInSchemeOrUserInfo_), ':');
}
- if (this.domain_) {
+ var domain = this.getDomain();
+ if (domain) {
out.push('//');
- if (this.userInfo_) {
+ var userInfo = this.getUserInfo();
+ if (userInfo) {
out.push(goog.Uri.encodeSpecialChars_(
- this.userInfo_, goog.Uri.reDisallowedInSchemeOrUserInfo_), '@');
+ userInfo, goog.Uri.reDisallowedInSchemeOrUserInfo_), '@');
}
- out.push(goog.Uri.encodeString_(this.domain_));
+ out.push(goog.string.urlEncode(domain));
- if (this.port_ != null) {
- out.push(':', String(this.getPort()));
+ var port = this.getPort();
+ if (port != null) {
+ out.push(':', String(port));
}
}
- if (this.path_) {
- if (this.hasDomain() && this.path_.charAt(0) != '/') {
+ var path = this.getPath();
+ if (path) {
+ if (this.hasDomain() && path.charAt(0) != '/') {
out.push('/');
}
out.push(goog.Uri.encodeSpecialChars_(
- this.path_,
- this.path_.charAt(0) == '/' ?
+ path,
+ path.charAt(0) == '/' ?
goog.Uri.reDisallowedInAbsolutePath_ :
goog.Uri.reDisallowedInRelativePath_));
}
- var query = String(this.queryData_);
+ var query = this.getEncodedQuery();
if (query) {
out.push('?', query);
}
- if (this.fragment_) {
+ var fragment = this.getFragment();
+ if (fragment) {
out.push('#', goog.Uri.encodeSpecialChars_(
- this.fragment_, goog.Uri.reDisallowedInFragment_));
+ fragment, goog.Uri.reDisallowedInFragment_));
}
- return this.cachedToString_ = out.join('');
+ return out.join('');
};
@@ -304,7 +322,7 @@ goog.Uri.prototype.resolve = function(relativeUri) {
}
if (overridden) {
- absoluteUri.setQuery(relativeUri.getDecodedQuery());
+ absoluteUri.setQueryData(relativeUri.getDecodedQuery());
} else {
overridden = relativeUri.hasFragment();
}
@@ -322,9 +340,7 @@ goog.Uri.prototype.resolve = function(relativeUri) {
* @return {!goog.Uri} New instance of the URI objcet.
*/
goog.Uri.prototype.clone = function() {
- return goog.Uri.create(this.scheme_, this.userInfo_, this.domain_,
- this.port_, this.path_, this.queryData_.clone(),
- this.fragment_, this.ignoreCase_);
+ return new goog.Uri(this);
};
@@ -344,7 +360,6 @@ goog.Uri.prototype.getScheme = function() {
*/
goog.Uri.prototype.setScheme = function(newScheme, opt_decode) {
this.enforceReadOnly();
- delete this.cachedToString_;
this.scheme_ = opt_decode ? goog.Uri.decodeOrEmpty_(newScheme) : newScheme;
// remove an : at the end of the scheme so somebody can pass in
@@ -380,7 +395,6 @@ goog.Uri.prototype.getUserInfo = function() {
*/
goog.Uri.prototype.setUserInfo = function(newUserInfo, opt_decode) {
this.enforceReadOnly();
- delete this.cachedToString_;
this.userInfo_ = opt_decode ? goog.Uri.decodeOrEmpty_(newUserInfo) :
newUserInfo;
return this;
@@ -411,7 +425,6 @@ goog.Uri.prototype.getDomain = function() {
*/
goog.Uri.prototype.setDomain = function(newDomain, opt_decode) {
this.enforceReadOnly();
- delete this.cachedToString_;
this.domain_ = opt_decode ? goog.Uri.decodeOrEmpty_(newDomain) : newDomain;
return this;
};
@@ -440,7 +453,6 @@ goog.Uri.prototype.getPort = function() {
*/
goog.Uri.prototype.setPort = function(newPort) {
this.enforceReadOnly();
- delete this.cachedToString_;
if (newPort) {
newPort = Number(newPort);
@@ -480,7 +492,6 @@ goog.Uri.prototype.getPath = function() {
*/
goog.Uri.prototype.setPath = function(newPath, opt_decode) {
this.enforceReadOnly();
- delete this.cachedToString_;
this.path_ = opt_decode ? goog.Uri.decodeOrEmpty_(newPath) : newPath;
return this;
};
@@ -511,21 +522,18 @@ goog.Uri.prototype.hasQuery = function() {
*/
goog.Uri.prototype.setQueryData = function(queryData, opt_decode) {
this.enforceReadOnly();
- delete this.cachedToString_;
if (queryData instanceof goog.Uri.QueryData) {
this.queryData_ = queryData;
- this.queryData_.uri_ = this;
this.queryData_.setIgnoreCase(this.ignoreCase_);
} else {
- // QueryData accepts encoded query string,
- // so encode it if opt_decode flag is not true.
if (!opt_decode) {
+ // QueryData accepts encoded query string, so encode it if
+ // opt_decode flag is not true.
queryData = goog.Uri.encodeSpecialChars_(queryData,
goog.Uri.reDisallowedInQuery_);
}
- this.queryData_ =
- new goog.Uri.QueryData(queryData, this, this.ignoreCase_);
+ this.queryData_ = new goog.Uri.QueryData(queryData, null, this.ignoreCase_);
}
return this;
@@ -589,8 +597,6 @@ goog.Uri.prototype.getQuery = function() {
*/
goog.Uri.prototype.setParameterValue = function(key, value) {
this.enforceReadOnly();
- delete this.cachedToString_;
-
this.queryData_.set(key, value);
return this;
};
@@ -611,7 +617,6 @@ goog.Uri.prototype.setParameterValue = function(key, value) {
*/
goog.Uri.prototype.setParameterValues = function(key, values) {
this.enforceReadOnly();
- delete this.cachedToString_;
if (!goog.isArray(values)) {
values = [String(values)];
@@ -640,12 +645,15 @@ goog.Uri.prototype.getParameterValues = function(name) {
* Returns the first value for a given cgi parameter or undefined if the given
* parameter name does not appear in the query string.
* @param {string} paramName Unescaped parameter name.
- * @return {*} The first value for a given cgi parameter or
+ * @return {string|undefined} The first value for a given cgi parameter or
* undefined if the given parameter name does not appear in the query
* string.
*/
goog.Uri.prototype.getParameterValue = function(paramName) {
- return this.queryData_.get(paramName);
+ // NOTE(nicksantos): This type-cast is a lie when
+ // preserveParameterTypesCompatibilityFlag is set to true.
+ // But this should only be set to true in tests.
+ return /** @type {string|undefined} */ (this.queryData_.get(paramName));
};
@@ -665,7 +673,6 @@ goog.Uri.prototype.getFragment = function() {
*/
goog.Uri.prototype.setFragment = function(newFragment, opt_decode) {
this.enforceReadOnly();
- delete this.cachedToString_;
this.fragment_ = opt_decode ? goog.Uri.decodeOrEmpty_(newFragment) :
newFragment;
return this;
@@ -909,28 +916,6 @@ goog.Uri.decodeOrEmpty_ = function(val) {
/**
- * URI encode a string, or return null if it's not a string.
- * @param {*} unescapedPart Unescaped string.
- * @return {?string} Escaped string.
- * @private
- */
-goog.Uri.encodeString_ = function(unescapedPart) {
- if (goog.isString(unescapedPart)) {
- return encodeURIComponent(unescapedPart);
- }
- return null;
-};
-
-
-/**
- * Regular expression used for determining if a string needs to be encoded.
- * @type {RegExp}
- * @private
- */
-goog.Uri.encodeSpecialRegExp_ = /^[a-zA-Z0-9\-_.!~*'():\/;?]*$/;
-
-
-/**
* If unescapedPart is non null, then escapes any characters in it that aren't
* valid characters in a url and also escapes any special characters that
* appear in extra.
@@ -941,21 +926,10 @@ goog.Uri.encodeSpecialRegExp_ = /^[a-zA-Z0-9\-_.!~*'():\/;?]*$/;
* @private
*/
goog.Uri.encodeSpecialChars_ = function(unescapedPart, extra) {
- var ret = null;
if (goog.isString(unescapedPart)) {
- ret = unescapedPart;
- // Checking if the search matches before calling encodeURI avoids an extra
- // allocation in IE6
- if (!goog.Uri.encodeSpecialRegExp_.test(ret)) {
- ret = encodeURI(unescapedPart);
- }
- // Checking if the search matches before calling replace avoids an extra
- // allocation in IE6
- if (ret.search(extra) >= 0) {
- ret = ret.replace(extra, goog.Uri.encodeChar_);
- }
+ return encodeURI(unescapedPart).replace(extra, goog.Uri.encodeChar_);
}
- return ret;
+ return null;
};
@@ -1039,8 +1013,9 @@ goog.Uri.haveSameDomain = function(uri1String, uri2String) {
*
* @param {?string=} opt_query Optional encoded query string to parse into
* the object.
- * @param {goog.Uri=} opt_uri Optional uri object that should have its cache
- * invalidated when this object updates.
+ * @param {goog.Uri=} opt_uri Optional uri object that should have its
+ * cache invalidated when this object updates. Deprecated -- this
+ * is no longer required.
* @param {boolean=} opt_ignoreCase If true, ignore the case of the parameter
* name in #get.
* @constructor
@@ -1054,14 +1029,6 @@ goog.Uri.QueryData = function(opt_query, opt_uri, opt_ignoreCase) {
this.encodedQuery_ = opt_query || null;
/**
- * Reference to a uri object which uses the query data. This allows the
- * QueryData object to invalidate the cache.
- * @type {goog.Uri}
- * @private
- */
- this.uri_ = opt_uri || null;
-
- /**
* If true, ignore the case of the parameter name in #get.
* @type {boolean}
* @private
@@ -1104,8 +1071,10 @@ goog.Uri.QueryData.prototype.ensureKeyMapInitialized_ = function() {
/**
* Creates a new query data instance from a map of names and values.
*
- * @param {!goog.structs.Map|!Object} map Map of string parameter names to
- * string parameter values.
+ * @param {!goog.structs.Map|!Object} map Map of string parameter
+ * names to parameter value. If parameter value is an array, it is
+ * treated as if the key maps to each individual value in the
+ * array.
* @param {goog.Uri=} opt_uri URI object that should have its cache
* invalidated when this object updates.
* @param {boolean=} opt_ignoreCase If true, ignore the case of the parameter
@@ -1117,11 +1086,19 @@ goog.Uri.QueryData.createFromMap = function(map, opt_uri, opt_ignoreCase) {
if (typeof keys == 'undefined') {
throw Error('Keys are undefined');
}
- return goog.Uri.QueryData.createFromKeysValues(
- keys,
- goog.structs.getValues(map),
- opt_uri,
- opt_ignoreCase);
+
+ var queryData = new goog.Uri.QueryData(null, null, opt_ignoreCase);
+ var values = goog.structs.getValues(map);
+ for (var i = 0; i < keys.length; i++) {
+ var key = keys[i];
+ var value = values[i];
+ if (!goog.isArray(value)) {
+ queryData.add(key, value);
+ } else {
+ queryData.setValues(key, value);
+ }
+ }
+ return queryData;
};
@@ -1143,7 +1120,7 @@ goog.Uri.QueryData.createFromKeysValues = function(
if (keys.length != values.length) {
throw Error('Mismatched lengths for keys/values');
}
- var queryData = new goog.Uri.QueryData(null, opt_uri, opt_ignoreCase);
+ var queryData = new goog.Uri.QueryData(null, null, opt_ignoreCase);
for (var i = 0; i < keys.length; i++) {
queryData.add(keys[i], values[i]);
}
@@ -1158,7 +1135,7 @@ goog.Uri.QueryData.createFromKeysValues = function(
* We need to use a Map because we cannot guarantee that the key names will
* not be problematic for IE.
*
- * @type {Object}
+ * @type {goog.structs.Map}
* @private
*/
goog.Uri.QueryData.prototype.keyMap_ = null;
@@ -1173,14 +1150,6 @@ goog.Uri.QueryData.prototype.count_ = null;
/**
- * Decoded query string, or null if it requires computing.
- * @type {?string}
- * @private
- */
-goog.Uri.QueryData.decodedQuery_ = null;
-
-
-/**
* @return {?number} The number of parameters.
*/
goog.Uri.QueryData.prototype.getCount = function() {
@@ -1200,19 +1169,12 @@ goog.Uri.QueryData.prototype.add = function(key, value) {
this.invalidateCache_();
key = this.getKeyName_(key);
- if (!this.containsKey(key)) {
- this.keyMap_.set(key, value);
- } else {
- var current = this.keyMap_.get(key);
- if (goog.isArray(current)) {
- current.push(value);
- } else {
- this.keyMap_.set(key, [current, value]);
- }
+ var values = this.keyMap_.get(key);
+ if (!values) {
+ this.keyMap_.set(key, (values = []));
}
-
+ values.push(value);
this.count_++;
-
return this;
};
@@ -1229,13 +1191,8 @@ goog.Uri.QueryData.prototype.remove = function(key) {
if (this.keyMap_.containsKey(key)) {
this.invalidateCache_();
- // we need to get it to know how many to decrement the count with
- var old = this.keyMap_.get(key);
- if (goog.isArray(old)) {
- this.count_ -= old.length;
- } else {
- this.count_--;
- }
+ // Decrement parameter count.
+ this.count_ -= this.keyMap_.get(key).length;
return this.keyMap_.remove(key);
}
return false;
@@ -1247,9 +1204,7 @@ goog.Uri.QueryData.prototype.remove = function(key) {
*/
goog.Uri.QueryData.prototype.clear = function() {
this.invalidateCache_();
- if (this.keyMap_) {
- this.keyMap_.clear();
- }
+ this.keyMap_ = null;
this.count_ = 0;
};
@@ -1292,21 +1247,17 @@ goog.Uri.QueryData.prototype.containsValue = function(value) {
/**
* Returns all the keys of the parameters. If a key is used multiple times
* it will be included multiple times in the returned array
- * @return {Array} All the keys of the parameters.
+ * @return {!Array} All the keys of the parameters.
*/
goog.Uri.QueryData.prototype.getKeys = function() {
this.ensureKeyMapInitialized_();
// We need to get the values to know how many keys to add.
- var vals = this.keyMap_.getValues(); // Array.<Array|String>
- var keys = this.keyMap_.getKeys(); // Array.<String>
+ var vals = /** @type {Array.<Array|*>} */ (this.keyMap_.getValues());
+ var keys = this.keyMap_.getKeys();
var rv = [];
for (var i = 0; i < keys.length; i++) {
var val = vals[i];
- if (goog.isArray(val)) {
- for (var j = 0; j < val.length; j++) {
- rv.push(keys[i]);
- }
- } else {
+ for (var j = 0; j < val.length; j++) {
rv.push(keys[i]);
}
}
@@ -1319,35 +1270,20 @@ goog.Uri.QueryData.prototype.getKeys = function() {
* data has no such key this will return an empty array. If no key is given
* all values wil be returned.
* @param {string=} opt_key The name of the parameter to get the values for.
- * @return {Array} All the values of the parameters with the given name.
+ * @return {!Array} All the values of the parameters with the given name.
*/
goog.Uri.QueryData.prototype.getValues = function(opt_key) {
this.ensureKeyMapInitialized_();
- var rv;
+ var rv = [];
if (opt_key) {
- var key = this.getKeyName_(opt_key);
- if (this.containsKey(key)) {
- var value = this.keyMap_.get(key);
- if (goog.isArray(value)) {
- return value;
- } else {
- rv = [];
- rv.push(value);
- }
- } else {
- rv = [];
+ if (this.containsKey(opt_key)) {
+ rv = goog.array.concat(rv, this.keyMap_.get(this.getKeyName_(opt_key)));
}
} else {
- // return all values
- var vals = this.keyMap_.getValues(); // Array.<Array|String>
- rv = [];
- for (var i = 0; i < vals.length; i++) {
- var val = vals[i];
- if (goog.isArray(val)) {
- goog.array.extend(rv, val);
- } else {
- rv.push(val);
- }
+ // Return all values.
+ var values = /** @type {Array.<Array|*>} */ (this.keyMap_.getValues());
+ for (var i = 0; i < values.length; i++) {
+ rv = goog.array.concat(rv, values[i]);
}
}
return rv;
@@ -1365,17 +1301,16 @@ goog.Uri.QueryData.prototype.set = function(key, value) {
this.ensureKeyMapInitialized_();
this.invalidateCache_();
+ // TODO(user): This could be better written as
+ // this.remove(key), this.add(key, value), but that would reorder
+ // the key (since the key is first removed and then added at the
+ // end) and we would have to fix unit tests that depend on key
+ // ordering.
key = this.getKeyName_(key);
if (this.containsKey(key)) {
- var old = this.keyMap_.get(key);
- if (goog.isArray(old)) {
- this.count_ -= old.length;
- } else {
- this.count_--;
- }
+ this.count_ -= this.keyMap_.get(key).length;
}
-
- this.keyMap_.set(key, value);
+ this.keyMap_.set(key, [value]);
this.count_++;
return this;
};
@@ -1387,46 +1322,31 @@ goog.Uri.QueryData.prototype.set = function(key, value) {
* @param {string} key The name of the parameter to get the value for.
* @param {*=} opt_default The default value to return if the query data
* has no such key.
- * @return {*} The first value associated with the key.
+ * @return {*} The first string value associated with the key, or opt_default
+ * if there's no value.
*/
goog.Uri.QueryData.prototype.get = function(key, opt_default) {
- this.ensureKeyMapInitialized_();
- key = this.getKeyName_(key);
- if (this.containsKey(key)) {
- var val = this.keyMap_.get(key);
- if (goog.isArray(val)) {
- return val[0];
- } else {
- return val;
- }
+ var values = key ? this.getValues(key) : [];
+ if (goog.Uri.preserveParameterTypesCompatibilityFlag) {
+ return values.length > 0 ? values[0] : opt_default;
} else {
- return opt_default;
+ return values.length > 0 ? String(values[0]) : opt_default;
}
};
/**
- * Sets the values for a key, if the key has already got values defined, this
- * will override the existing values then remove any left over
+ * Sets the values for a key. If the key already exists, this will
+ * override all of the existing values that correspond to the key.
* @param {string} key The key to set values for.
* @param {Array} values The values to set.
*/
goog.Uri.QueryData.prototype.setValues = function(key, values) {
- this.ensureKeyMapInitialized_();
- this.invalidateCache_();
-
- key = this.getKeyName_(key);
- if (this.containsKey(key)) {
- var old = this.keyMap_.get(key);
- if (goog.isArray(old)) {
- this.count_ -= old.length;
- } else {
- this.count_--;
- }
- }
+ this.remove(key);
if (values.length > 0) {
- this.keyMap_.set(key, values);
+ this.invalidateCache_();
+ this.keyMap_.set(this.getKeyName_(key), goog.array.clone(values));
this.count_ += values.length;
}
};
@@ -1434,6 +1354,7 @@ goog.Uri.QueryData.prototype.setValues = function(key, values) {
/**
* @return {string} Encoded query string.
+ * @override
*/
goog.Uri.QueryData.prototype.toString = function() {
if (this.encodedQuery_) {
@@ -1446,42 +1367,26 @@ goog.Uri.QueryData.prototype.toString = function() {
var sb = [];
- // this used to use this.getKeys and this.getVals but that generates a lot
- // allocations than just iterating over the keys
- var count = 0;
+ // In the past, we use this.getKeys() and this.getVals(), but that
+ // generates a lot of allocations as compared to simply iterating
+ // over the keys.
var keys = this.keyMap_.getKeys();
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var encodedKey = goog.string.urlEncode(key);
- var val = this.keyMap_.get(key);
- if (goog.isArray(val)) {
- for (var j = 0; j < val.length; j++) {
- if (count > 0) {
- sb.push('&');
- }
- sb.push(encodedKey);
- // Check for empty string, null and undefined get encoded
- // into the url as literal strings
- if (val[j] !== '') {
- sb.push('=', goog.string.urlEncode(val[j]));
- }
- count++;
- }
- } else {
- if (count > 0) {
- sb.push('&');
- }
- sb.push(encodedKey);
- // Check for empty string, null and undefined get encoded
- // into the url as literal strings
- if (val !== '') {
- sb.push('=', goog.string.urlEncode(val));
+ var val = this.getValues(key);
+ for (var j = 0; j < val.length; j++) {
+ var param = encodedKey;
+ // Ensure that null and undefined are encoded into the url as
+ // literal strings.
+ if (val[j] !== '') {
+ param += '=' + goog.string.urlEncode(val[j]);
}
- count++;
+ sb.push(param);
}
}
- return this.encodedQuery_ = sb.join('');
+ return this.encodedQuery_ = sb.join('&');
};
@@ -1489,11 +1394,7 @@ goog.Uri.QueryData.prototype.toString = function() {
* @return {string} Decoded query string.
*/
goog.Uri.QueryData.prototype.toDecodedString = function() {
- if (!this.decodedQuery_) {
- this.decodedQuery_ = goog.Uri.decodeOrEmpty_(this.toString());
- }
-
- return this.decodedQuery_;
+ return goog.Uri.decodeOrEmpty_(this.toString());
};
@@ -1502,11 +1403,7 @@ goog.Uri.QueryData.prototype.toDecodedString = function() {
* @private
*/
goog.Uri.QueryData.prototype.invalidateCache_ = function() {
- delete this.decodedQuery_;
- delete this.encodedQuery_;
- if (this.uri_) {
- delete this.uri_.cachedToString_;
- }
+ this.encodedQuery_ = null;
};
@@ -1534,14 +1431,10 @@ goog.Uri.QueryData.prototype.filterKeys = function(keys) {
*/
goog.Uri.QueryData.prototype.clone = function() {
var rv = new goog.Uri.QueryData();
- if (this.decodedQuery_) {
- rv.decodedQuery_ = this.decodedQuery_;
- }
- if (this.encodedQuery_) {
- rv.encodedQuery_ = this.encodedQuery_;
- }
+ rv.encodedQuery_ = this.encodedQuery_;
if (this.keyMap_) {
rv.keyMap_ = this.keyMap_.clone();
+ rv.count_ = this.count_;
}
return rv;
};
@@ -1576,11 +1469,11 @@ goog.Uri.QueryData.prototype.setIgnoreCase = function(ignoreCase) {
this.invalidateCache_();
goog.structs.forEach(this.keyMap_,
/** @this {goog.Uri.QueryData} */
- function(value, key, map) {
+ function(value, key) {
var lowerCase = key.toLowerCase();
if (key != lowerCase) {
this.remove(key);
- this.add(lowerCase, value);
+ this.setValues(lowerCase, value);
}
}, this);
}