Skip to content

Commit aaa8999

Browse files
fix(Resolvable): Make resolveResolvable use a subset of the overall resolve Path (from path root to the resolve's state), so it injects the proper objects.
This fixes a problem where a resolve at a parent state injects a resolve overridden in a child state. Another scenario this fixes is when a parent resolve defines a resolve which is named the same as a service it depends on (it's in the sample app). To properly inject the service, we need to exclude the resolve/service name when getting the available resolvables from the path context. This happens by filtering the resolve's own name from the *last* path element, so if the path is incorrectly provided, the name is also filtered incorrectly.
1 parent bbbd298 commit aaa8999

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

src/resolve/resolvable.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import trace from "../common/trace";
55
import {IPromise} from "angular";
66
import {IState} from "../state/interface";
77
import {runtime} from "../common/angular1"
8+
import Path from "./path"
89

910
/**
1011
* The basic building block for the resolve system.
@@ -45,13 +46,13 @@ export default class Resolvable {
4546
// - wait for resolveFn promise to resolve
4647
// - store unwrapped data
4748
// - resolve the Resolvable's promise
48-
resolveResolvable(pathContext, options) {
49+
resolveResolvable(path: Path, options) {
4950
options = options || {};
5051
if (options.trace) trace.traceResolveResolvable(this, options);
5152
// First, set up an overall deferred/promise for this Resolvable
5253
var deferred = runtime.$q.defer();
5354
this.promise = deferred.promise;
54-
55+
var pathContext = path.pathFromRoot(path.elementForState(this.state));
5556
// Load a map of all resolvables for this state from the context path
5657
// Omit the current Resolvable from the result, so we don't try to inject this into this
5758
var ancestorsByName = pathContext.getResolvables({ omitOwnLocals: [ this.name ] });

test/resolveSpec.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ var resolve = uiRouter.resolve,
1515

1616
var statesTree, statesMap = {};
1717
var emptyPath;
18-
var counts, expectCounts;
18+
var vals, counts, expectCounts;
1919
var asyncCount;
2020

2121
beforeEach(function () {
22-
counts = { _J: 0, _J2: 0, _K: 0, _L: 0, _M: 0};
22+
counts = { _J: 0, _J2: 0, _K: 0, _L: 0, _M: 0, _Q: 0 };
23+
vals = { _Q: null };
2324
expectCounts = angular.copy(counts);
2425
states = {
2526
A: { resolve: { _A: function () { return "A"; }, _A2: function() { return "A2"; }},
@@ -47,7 +48,9 @@ beforeEach(function () {
4748
resolvePolicy: { _N: "eager", _N2: "lazy", _N3: "jit" }
4849
}
4950
},
50-
O: { resolve: { _O: function(_O2) { return _O2 + "O"; }, _O2: function(_O) { return _O + "O2"; } }
51+
O: { resolve: { _O: function(_O2) { return _O2 + "O"; }, _O2: function(_O) { return _O + "O2"; } } },
52+
P: { resolve: { $state: function($state) { return $state } },
53+
Q: { resolve: { _Q: function($state) { counts._Q++; vals._Q = $state; return "foo"; }}}
5154
}
5255
};
5356

@@ -180,6 +183,21 @@ describe('Resolvables system:', function () {
180183
asyncCount++;
181184
});
182185

186+
$q.flush();
187+
expect(asyncCount).toBe(1);
188+
}));
189+
190+
it('should provide each resolveResolvable with a path context, starting from the root to the resolves PathElement', inject(function($q, $state) {
191+
"use strict";
192+
var path = makePath(["P", "Q"]);
193+
var promise = path.resolvePath({ resolvePolicy: "jit" });
194+
195+
promise.then(function () {
196+
expect(getResolvedData(path)).toEqualData({ $state: $state, _Q: "foo" });
197+
asyncCount++;
198+
});
199+
200+
183201
$q.flush();
184202
expect(asyncCount).toBe(1);
185203
}));

0 commit comments

Comments
 (0)