Skip to content

Commit 6deee59

Browse files
chore(all): continue fixing broken code. 32 non-passing tests remain.
docs($resolve): improve ResolveContext docs chore(lint): linted chore($resolve): remove unused and commented-out code chore($transition): rename runAsync() to just run() chore($state): provide $state to StateQueueManager() chore($state): remove unused and commented-out code. chore($state): default options to {} in transitionTo() chore($state): use transition.to() in transitionSuccess()
1 parent 1303697 commit 6deee59

File tree

3 files changed

+54
-98
lines changed

3 files changed

+54
-98
lines changed

src/resolve.js

+46-69
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ function $Resolve( $q, $injector) {
127127
policyConf[resolvable.name] = resolvePolicies[policyString];
128128
});
129129

130-
var resolvablesForPolicy = filter(resolvables, function(resolvable) { return policyConf[resolvable.name] >= policyOrdinal });
130+
var resolvablesForPolicy = filter(resolvables, function(resolvable) { return policyConf[resolvable.name] >= policyOrdinal; });
131131
return $q.all(map(resolvablesForPolicy, function(resolvable) { return resolvable.get(resolveContext); }));
132132
}
133133

@@ -179,6 +179,9 @@ function $Resolve( $q, $injector) {
179179

180180
// statesOrPathElements must be an array of either state(s) or PathElement(s)
181181
// states could be "public" state objects for this?
182+
/*
183+
Path becomes the replacement data structure for $state.$current.locals. This is now stored on the $transition closure in _fromPath.
184+
*/
182185
Path = function Path(statesOrPathElements) {
183186
var self = this;
184187
if (!isArray(statesOrPathElements)) throw new Error("states must be an array of state(s) or PathElement(s)", statesOrPathElements);
@@ -199,32 +202,10 @@ function $Resolve( $q, $injector) {
199202
function resolveContext(toPathElement) {
200203
toPathElement = toPathElement || elements[elements.length - 1];
201204
var elementIdx = elements.indexOf(toPathElement);
202-
// if (angular.isNumber(toPathElement)) // maybe allow the param to be the index too
203-
// elementIdx = toPathElement;
204205
if (elementIdx == -1) throw new Error("this Path does not contain the toPathElement");
205206
return new ResolveContext(self.slice(0, elementIdx));
206207
}
207208

208-
// Not used
209-
function invoke(hook, self, locals) {
210-
if (!hook) return;
211-
return $injector.invoke(hook, self, locals);
212-
}
213-
214-
function invokeFunctionsSync(path, fnName, reverse) {
215-
var pathElements = elements.slice(0);
216-
if (reverse) pathElements.reverse();
217-
218-
forEach(pathElements, function(pathElement) {
219-
var fn = pathElement.state[fnName];
220-
if (fn) {
221-
var result = pathElement.invokeNow(fn, {}, path.resolveContext(pathElement));
222-
if (!result) return result;
223-
}
224-
});
225-
return true;
226-
}
227-
228209
// Public API
229210
extend(this, {
230211
resolve: resolvePath,
@@ -242,67 +223,63 @@ function $Resolve( $q, $injector) {
242223
},
243224
states: function() {
244225
return pluck(elements, "state");
245-
},
246-
$$enter: function(toPath, async) {
247-
// Async returns promise for true/false. Don't need to pre-resolve anything
248-
if (async) return invokeFunctionsAsync(toPath, 'onEnter', false);
249-
// Sync returns truthy/falsy ... all deps must be pre-resolved in toPath
250-
if (async)
251-
return invokeFunctionsSync(toPath, 'onEnter', false);
252-
},
253-
$$exit: function(fromPath, async) {
254-
if (async) return invokeFunctionsAsync(fromPath, 'onExit', true);
255-
return invokeFunctionsSync(fromPath, 'onExit', true);
256226
}
257227
});
258228
};
259229

260-
// ResolveContext is passed into each resolve() function, and is used to statefully manage Resolve status.
261-
// ResolveContext is essentially the replacement data structure for $state.$current.locals and we'll have to
262-
// figure out where to store/manage this data structure.
263-
// It manages a set of Resolvables that are available at each level of the Path.
264-
// It follows the list of PathElements and inherit()s the PathElement's Resolvables on top of the
265-
// previous PathElement's Resolvables. i.e., it builds a prototypal chain for the PathElements' Resolvables.
266-
// Before moving on to the next PathElement, it makes a note of what Resolvables are available for the current
267-
// PathElement, and maps it by state name.
268-
269-
// ResolveContext constructor takes a path which is assumed to be partially resolved, or
270-
// not resolved at all, which we're in process of resolving
230+
/**
231+
* ResolveContext provides injectable dependencies (Resolvables) to the three resolve() functions (Path.resolve,
232+
* PathElement.resolve, and Resolvable.resolve).
233+
*
234+
* The ResolveContext constructor takes a Path(), from which the ResolvableContext is built. The Path contains
235+
* PathElements, which each in turn contain a Resolvables map. Each Resolvable may or may not be pre-resolved.
236+
*
237+
* For each PathElement in the Path, ResolveContext maps the available Resolvables. Each PathElement is provided with
238+
* the Resolvables at its own level, as well as the aggregated Resolvables of its parent PathElement(s). Aggregation is
239+
* done using prototypal inheritance from the parent's Resolvable(s) map.
240+
*/
271241
ResolveContext = function ResolveContext(path) {
272242
if (path === undefined) path = new Path([]);
273243
var resolvablesByState = {}, previousIteration = {};
274244

275245
forEach(path.elements, function (pathElem) {
276246
var resolvablesForPE = pathElem.resolvables;
277-
var resolvesbyName = indexBy(resolvablesForPE, 'name');
278-
var resolvables = inherit(previousIteration, resolvesbyName); // note prototypal inheritance
247+
var resolvesByName = indexBy(resolvablesForPE, 'name');
248+
var resolvables = inherit(previousIteration, resolvesByName); // note prototypal inheritance
279249
previousIteration = resolvablesByState[pathElem.state.name] = resolvables;
280250
});
281251

282-
// Gets resolvables available for a particular state.
283-
// TODO: This should probably be "for a particular PathElement" instead of state, but PathElements encapsulate a state.
284-
// This returns the Resolvable map by state name.
285-
286-
// options.omitPropsFromPrototype
287-
// Remove the props specified in options.omitPropsFromPrototype from the prototype of the object.
288-
289-
// This hides a top-level resolvable by name, potentially exposing a parent resolvable of the same name
290-
// further down the prototype chain.
291-
292-
// This is used to provide a Resolvable access to all other Resolvables in its same PathElement, yet disallow
293-
// that Resolvable access to its own injectable Resolvable reference.
294-
295-
// This is also used to allow a state to override a parent state's resolve while also injecting
296-
// that parent state's resolve:
297252

298-
// state({ name: 'G', resolve: { _G: function() { return "G"; } } });
299-
// state({ name: 'G.G2', resolve: { _G: function(_G) { return _G + "G2"; } } });
300-
// where injecting _G into a controller will yield "GG2"
301253

302-
// options.flatten
303-
// $$resolvablesByState has resolvables organized in a prototypal inheritance chain. options.flatten will
304-
// flatten the object from prototypal inheritance to a simple object with all its prototype chain properties
305-
// exposed with child properties taking precedence over parent properties.
254+
/**
255+
* Gets the available Resolvables for a particular PathElement (mapped by the PathElement's state name).
256+
*
257+
* @param stateName
258+
* @param options
259+
*
260+
* options.flatten
261+
* Return the Resolvables as a standard object map, not a prototypally inherited object map.
262+
*
263+
* $$resolvablesByState has resolvables organized in a prototypal inheritance chain. options.flatten will
264+
* flatten the object from prototypal inheritance to a simple object with all its prototype chain properties
265+
* exposed, where child properties take precedence over parent properties.
266+
*
267+
* options.omitPropsFromPrototype
268+
* Remove the props specified in options.omitPropsFromPrototype from the prototype of the object.
269+
*
270+
* This will hide a top-level resolvable (by name), potentially exposing a parent resolvable of the same name
271+
* further down the prototype chain.
272+
*
273+
* This is used by Resolvable.resolve(resolveContext) in order to provide the Resolvable access to all the other
274+
* Resolvables at its own PathElement level, yet disallow that Resolvable access to its own injectable Resolvable.
275+
*
276+
* This is also used to allow a state to override a parent state's resolve while also injecting
277+
* that parent state's resolve:
278+
*
279+
* state({ name: 'G', resolve: { _G: function() { return "G"; } } });
280+
* state({ name: 'G.G2', resolve: { _G: function(_G) { return _G + "G2"; } } });
281+
* where injecting _G into a controller will yield "GG2"
282+
*/
306283
function getResolvableLocals(stateName, options) {
307284
var resolvables = (resolvablesByState[stateName] || {});
308285
options = extend({ flatten: true, omitPropsFromPrototype: [] }, options);

src/state.js

+6-17
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ var GlobBuilder = (function() {
4444
})();
4545

4646

47-
function StateQueueManager(states, builder, $urlRouterProvider) {
47+
function StateQueueManager(states, builder, $urlRouterProvider, $state) {
4848
var queue = [], abstractKey = 'abstract';
4949

5050
extend(this, {
@@ -301,7 +301,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactoryProvider) {
301301

302302
var matcher = new StateMatcher(states);
303303
var builder = new StateBuilder(function() { return root; }, matcher, $urlMatcherFactoryProvider);
304-
var queue = new StateQueueManager(states, builder, $urlRouterProvider);
304+
var queue = new StateQueueManager(states, builder, $urlRouterProvider, $state);
305305

306306
function $state() {}
307307

@@ -751,13 +751,14 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactoryProvider) {
751751
* {@link ui.router.state.$state#methods_go $state.go}.
752752
*/
753753
$state.transitionTo = function transitionTo(to, toParams, options) {
754+
options = options || {};
754755
var transition = $transition.start(to, toParams || {}, extend({
755756
location: true,
756757
relative: null,
757758
inherit: false,
758759
notify: true,
759760
reload: false
760-
}, options || {}));
761+
}, options));
761762

762763
var stateHandler = {
763764
retryIfNotFound: function(transition) {
@@ -858,6 +859,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactoryProvider) {
858859

859860

860861
function transitionSuccess() {
862+
var to = transition.to();
861863
// Update globals in $state
862864
$state.$current = to;
863865
$state.current = to.self;
@@ -921,25 +923,12 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactoryProvider) {
921923
// and return a promise for the new state. We also keep track of what the
922924
// current promise is, so that we can detect overlapping transitions and
923925
// keep only the outcome of the last transition.
924-
var current = transition.runAsync()
926+
var current = transition.run()
925927
.then(function(data) {
926-
console.log("hur", data);
927928
transitionSuccess();
928929
return data;
929930
}, transitionFailure);
930931

931-
// var current = resolved.then(function() {
932-
// var isCurrentTransition = function () { return $state.transition === current; };
933-
// var result = transition.begin(isCurrentTransition, transition.run);
934-
//
935-
// if (result === transition.SUPERSEDED) return TransitionSuperseded;
936-
// if (result === transition.ABORTED) return TransitionAborted;
937-
// transition.end();
938-
// transitionSuccess();
939-
// return $state.current;
940-
//
941-
// }, transitionFailure);
942-
943932
return transition;
944933
};
945934

src/transition.js

+2-12
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ function $TransitionProvider() {
129129
.then(function(result) {
130130
return result ? result : $q.reject(transition.ABORTED);
131131
});
132-
}
132+
};
133133
}
134134

135135
function buildTransitionSteps() {
@@ -308,22 +308,12 @@ function $TransitionProvider() {
308308
ignored: function() {
309309
return (toState === fromState && !options.reload);
310310
},
311-
runAsync: function() {
311+
run: function() {
312312
calculateTreeChanges();
313313
var pathContext = new ResolveContext(toPath);
314314
return toPath.resolve(pathContext, { policy: "eager" })
315315
.then( buildTransitionSteps );
316316
},
317-
run: function() {
318-
// only the stuff necessary, and then run the onEnter/onExit callbacks synchronously to get a true/false here.
319-
var exiting = transition.exiting().$$exit(fromPath);
320-
if (exiting !== true) return exiting;
321-
322-
var entering = transition.entering().$$enter(toPath);
323-
if (entering !== true) return entering;
324-
325-
return true;
326-
},
327317
begin: function(compare, exec) {
328318
if (!compare()) return this.SUPERSEDED;
329319
if (!exec()) return this.ABORTED;

0 commit comments

Comments
 (0)