Skip to content

Commit

Permalink
fix($urlMatcherFactory): fixed ParamSet.$$keys() ordering
Browse files Browse the repository at this point in the history
- paramset uses prototypal inheritance, but ordering was not retained correctly.  Add a $$parent property so we can enumerate the properties of the prototypal chain appropriately.
  • Loading branch information
christopherthielen committed Nov 11, 2014
1 parent 872d085 commit 9136fec
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 7 deletions.
3 changes: 1 addition & 2 deletions src/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {

// Derive parameters for this state and ensure they're a super-set of parent's parameters
params: function(state) {
var parentParams = state.parent && state.parent.params || new $$UMFP.ParamSet();
return inherit(parentParams, state.ownParams);
return state.parent && state.parent.params ? extend(state.parent.params.$$new(), state.ownParams) : new $$UMFP.ParamSet();
},

// If there is no explicit multi-view configuration, make one up so we don't have
Expand Down
26 changes: 21 additions & 5 deletions src/urlMatcherFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ var $$UMFP; // reference to $UrlMatcherFactoryProvider
*
* @param {string} pattern The pattern to compile into a matcher.
* @param {Object} config A configuration object hash:
* @param {Object=} parentMatcher Used to concatenate the pattern/config onto
* an existing UrlMatcher
*
* * `caseInsensitive` - `true` if URL matching should be case insensitive, otherwise `false`, the default value (for backward compatibility) is `false`.
* * `strict` - `false` if matching against a URL with a trailing slash should be treated as equivalent to a URL without a trailing slash, the default value is `true`.
Expand All @@ -61,7 +63,7 @@ var $$UMFP; // reference to $UrlMatcherFactoryProvider
*
* @returns {Object} New `UrlMatcher` object
*/
function UrlMatcher(pattern, config) {
function UrlMatcher(pattern, config, parentMatcher) {
config = extend({ params: {} }, isObject(config) ? config : {});

// Find all placeholders and create a compiled pattern, using either classic or curly syntax:
Expand All @@ -81,9 +83,11 @@ function UrlMatcher(pattern, config) {
searchPlaceholder = /([:]?)([\w\[\]-]+)|\{([\w\[\]-]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,
compiled = '^', last = 0, m,
segments = this.segments = [],
params = this.params = new $$UMFP.ParamSet();
parentParams = parentMatcher ? parentMatcher.params : {},
params = this.params = parentMatcher ? parentMatcher.params.$$new() : new $$UMFP.ParamSet();

function addParameter(id, type, config, isSearch) {
if (parentParams[id]) return parentParams[id];
if (!/^\w+(-+\w+)*(?:\[\])?$/.test(id)) throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'");
if (params[id]) throw new Error("Duplicate parameter name '" + id + "' in pattern '" + pattern + "'");
params[id] = new $$UMFP.Param(id, type, config, isSearch);
Expand Down Expand Up @@ -189,7 +193,7 @@ UrlMatcher.prototype.concat = function (pattern, config) {
strict: $$UMFP.strictMode(),
squash: $$UMFP.defaultSquashPolicy()
};
return new UrlMatcher(this.sourcePath + pattern + this.sourceSearch, extend(defaultConfig, config));
return new UrlMatcher(this.sourcePath + pattern + this.sourceSearch, extend(defaultConfig, config), this);
};

UrlMatcher.prototype.toString = function () {
Expand Down Expand Up @@ -265,7 +269,7 @@ UrlMatcher.prototype.exec = function (path, searchParams) {
* pattern has no parameters, an empty array is returned.
*/
UrlMatcher.prototype.parameters = function (param) {
if (!isDefined(param)) return objectKeys(this.params);
if (!isDefined(param)) return this.params.$$keys();
return this.params[param] || null;
};

Expand Down Expand Up @@ -919,8 +923,20 @@ function $UrlMatcherFactory() {
}

ParamSet.prototype = {
$$new: function() {
return inherit(this, extend(new ParamSet(), { $$parent: this}));
},
$$keys: function () {
return protoKeys(this, ["$$keys", "$$values", "$$equals", "$$validates"]);
var keys = [], chain = [], parent = this,
ignore = ["$$keys", "$$values", "$$equals", "$$validates", "$$parent"];
while (parent) { chain.push(parent); parent = parent.$$parent; }
chain.reverse();
forEach(chain, function(paramset) {
forEach(objectKeys(paramset), function(key) {
if (keys.indexOf(key) === -1 && ignore.indexOf(key) === -1) keys.push(key);
});
});
return keys;
},
$$values: function(paramValues) {
var values = {}, self = this;
Expand Down

0 comments on commit 9136fec

Please sign in to comment.