Skip to content

Commit 1478a3c

Browse files
committed
fix(lazyLoad): StateBuilder should not mutate the state declaration
Fixed repeated {remainder:any} params error when future state is registered repeatedly. This scenario is typically happened during unit test. Related: 3cd5a2a#r31260154
1 parent 404dd31 commit 1478a3c

File tree

2 files changed

+15
-6
lines changed

2 files changed

+15
-6
lines changed

src/state/stateBuilder.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/** @publicapi @module state */ /** */
2-
import { applyPairs, extend, identity, inherit, mapObj, noop, Obj, omit, tail, values } from '../common/common';
2+
import { applyPairs, extend, identity, inherit, mapObj, noop, Obj, omit, tail, values, copy } from '../common/common';
33
import { isArray, isDefined, isFunction, isString } from '../common/predicates';
44
import { stringify } from '../common/strings';
55
import { is, pattern, pipe, prop, val } from '../common/hof';
@@ -57,17 +57,20 @@ function dataBuilder(state: StateObject) {
5757

5858
const getUrlBuilder = ($urlMatcherFactoryProvider: UrlMatcherFactory, root: () => StateObject) =>
5959
function urlBuilder(stateObject: StateObject) {
60-
const state: StateDeclaration = stateObject.self;
60+
let stateDec: StateDeclaration = stateObject.self;
6161

6262
// For future states, i.e., states whose name ends with `.**`,
6363
// match anything that starts with the url prefix
64-
if (state && state.url && state.name && state.name.match(/\.\*\*$/)) {
65-
state.url += '{remainder:any}'; // match any path (.*)
64+
if (stateDec && stateDec.url && stateDec.name && stateDec.name.match(/\.\*\*$/)) {
65+
const newStateDec: StateDeclaration = {};
66+
copy(stateDec, newStateDec);
67+
newStateDec.url += '{remainder:any}'; // match any path (.*)
68+
stateDec = newStateDec;
6669
}
6770

6871
const parent = stateObject.parent;
69-
const parsed = parseUrl(state.url);
70-
const url = !parsed ? state.url : $urlMatcherFactoryProvider.compile(parsed.val, { state });
72+
const parsed = parseUrl(stateDec.url);
73+
const url = !parsed ? stateDec.url : $urlMatcherFactoryProvider.compile(parsed.val, { state: stateDec });
7174

7275
if (!url) return null;
7376
if (!$urlMatcherFactoryProvider.isMatcher(url)) throw new Error(`Invalid url '${url}' in state '${stateObject}'`);

test/lazyLoadSpec.ts

+6
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ describe('future state', function() {
5353
expect($registry.get(state)).toBe(statedef);
5454
});
5555

56+
it('should not change the url of future states', () => {
57+
const statedef = { name: 'future.**', url: '/future' };
58+
const state = $registry.register(statedef);
59+
expect($registry.get(state).url).toBe('/future');
60+
});
61+
5662
it('should replace a future state when a normal state of the same name is registered', () => {
5763
const state = $registry.register({ name: 'future.**' });
5864

0 commit comments

Comments
 (0)