Skip to content

Commit 9cafc06

Browse files
BC-BREAK: remove ResolveContext.getResolvables() in favor of .getToken() and .getResolvable()`
BC-BREAK: remove `ResolveContext.invokeLater()` and `.invokeNow()` BC-BREAK: remove support for `JIT` resolves This also obviates the need for the `loadAllControllerLocals` hook
1 parent e4a1f19 commit 9cafc06

File tree

9 files changed

+58
-159
lines changed

9 files changed

+58
-159
lines changed

src/ng1/directives/viewDirective.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/** @module ng1_directives */ /** for typedoc */
22
"use strict";
3-
import {extend, map, unnestR, filter} from "../../common/common";
3+
import {extend, unnestR, filter} from "../../common/common";
44
import {isDefined, isFunction, isString} from "../../common/predicates";
55
import {trace} from "../../common/trace";
66
import {ActiveUIView} from "../../view/interface";
@@ -14,6 +14,7 @@ import {Param} from "../../params/param";
1414
import {kebobString} from "../../common/strings";
1515
import {HookRegOptions} from "../../transition/interface";
1616
import {Ng1Controller} from "../interface";
17+
import {getLocals} from "../services";
1718

1819
/** @hidden */
1920
export type UIViewData = {
@@ -335,7 +336,8 @@ function $ViewDirectiveFill ( $compile, $controller, $transitions, $view,
335336
let controllerAs: string = getControllerAs(cfg);
336337
let resolveAs: string = getResolveAs(cfg);
337338
let resolveCtx: ResolveContext = getResolveContext(cfg);
338-
let locals = resolveCtx && map(resolveCtx.getResolvables(), r => r.data);
339+
340+
let locals = resolveCtx && getLocals(resolveCtx);
339341

340342
scope[resolveAs] = locals;
341343

@@ -394,7 +396,7 @@ function registerControllerCallbacks($transitions: TransitionService, controller
394396
// Fire callback on any successful transition
395397
const paramsUpdated = ($transition$: Transition) => {
396398
let ctx: ResolveContext = cfg.node.resolveContext;
397-
let viewCreationTrans = ctx.getResolvables()['$transition$'].data;
399+
let viewCreationTrans = ctx.getResolvable('$transition$').data;
398400
// Exit early if the $transition$ is the same as the view was created within.
399401
// Exit early if the $transition$ will exit the state the view is for.
400402
if ($transition$ === viewCreationTrans || $transition$.exiting().indexOf(cfg.node.state.self) !== -1) return;

src/ng1/services.ts

+8-25
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
/** for typedoc */
1313
import {UIRouter} from "../router";
1414
import {services} from "../common/coreservices";
15-
import {map, bindFunctions, removeFrom, find, noop} from "../common/common";
15+
import {bindFunctions, removeFrom, applyPairs} from "../common/common";
1616
import {prop, propEq} from "../common/hof";
17-
import {isObject} from "../common/predicates";
17+
import {isObject, isString} from "../common/predicates";
1818
import {PathNode} from "../path/node";
1919
import {resolveFactory} from "./legacy/resolveService";
2020
import {trace} from "../common/trace";
@@ -28,6 +28,7 @@ import {UrlRouterProvider, UrlRouter} from "../url/urlRouter";
2828
import {UrlMatcherFactory} from "../url/urlMatcherFactory";
2929
import {Transition} from "../transition/transition";
3030
import {getStateHookBuilder} from "./statebuilders/onEnterExitRetain";
31+
import {ResolveContext} from "../resolve/resolveContext";
3132

3233
/** @hidden */
3334
let app = angular.module("ui.router.angular1", []);
@@ -255,29 +256,6 @@ angular.module('ui.router.state').factory('$stateParams', ['ng1UIRouter', (ng1UI
255256

256257
// $transitions service and $transitionsProvider
257258
function getTransitionsProvider() {
258-
// TODO: check if we can remove loadAllControllerLocals. Shouldn't be necessary without JIT resolve policy
259-
function loadAllControllerLocals($transition$: Transition) {
260-
const loadLocals = (vc: Ng1ViewConfig) => {
261-
let node = (<PathNode> find($transition$.treeChanges().to, propEq('state', vc.viewDecl.$context)));
262-
// Temporary fix; This whole callback should be nuked when fixing #2662
263-
if (!node) return services.$q.when();
264-
let resolveCtx = node.resolveContext;
265-
let controllerDeps = annotateController(vc.controller);
266-
let resolvables = resolveCtx.getResolvables();
267-
268-
function $loadControllerLocals() { }
269-
$loadControllerLocals.$inject = controllerDeps.filter(dep => resolvables.hasOwnProperty(dep));
270-
// Load any controller resolves that aren't already loaded
271-
return resolveCtx.invokeLater($loadControllerLocals)
272-
// Then provide the view config with all the resolved data
273-
.then(() => vc.locals = map(resolvables, res => res.data));
274-
};
275-
276-
let loadAllLocals = $transition$.views("entering").filter(vc => !!(<Ng1ViewConfig>vc).controller).map(loadLocals);
277-
return services.$q.all(loadAllLocals).then(noop);
278-
}
279-
router.transitionService.onFinish({}, loadAllControllerLocals);
280-
281259
router.transitionService["$get"] = () => router.transitionService;
282260
return router.transitionService;
283261
}
@@ -300,6 +278,11 @@ export function watchDigests($rootScope) {
300278
}
301279
angular.module("ui.router").run(watchDigests);
302280

281+
export const getLocals = (ctx: ResolveContext) => {
282+
let tokens = ctx.getTokens().filter(isString);
283+
let tuples = tokens.map(key => [ key, ctx.getResolvable(key).data ]);
284+
return tuples.reduce(applyPairs, {});
285+
};
303286

304287
/** Injectable services */
305288

src/ng1/statebuilders/onEnterExitRetain.ts

+3-6
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import {TransitionStateHookFn, HookResult} from "../../transition/interface";
44
import {Transition} from "../../transition/transition";
55
import IInjectorService = angular.auto.IInjectorService;
66
import {services} from "../../common/coreservices";
7-
import {isString} from "../../common/predicates";
8-
import {applyPairs} from "../../common/common";
7+
import {getLocals} from "../services";
8+
import {tail} from "../../common/common";
99

1010
/**
1111
* This is a [[StateBuilder.builder]] function for angular1 `onEnter`, `onExit`,
@@ -18,10 +18,7 @@ export const getStateHookBuilder = (hookName) =>
1818
function stateHookBuilder(state: State, parentFn): TransitionStateHookFn {
1919
let hook = state[hookName];
2020
function decoratedNg1Hook(trans: Transition, inj: IInjectorService): HookResult {
21-
let tokens = trans.getResolveTokens().filter(isString);
22-
let tuples = tokens.map(key => [ key, trans.getResolveValue(key) ]);
23-
let locals = tuples.reduce(applyPairs, {});
24-
21+
let locals = getLocals(tail(trans.treeChanges().to).resolveContext);
2522
return services.$injector.invoke(hook, this, locals);
2623
}
2724

src/ng1/statebuilders/views.ts

+14-10
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
/** @module ng1 */ /** */
22
import {State} from "../../state/stateObject";
3-
import {pick, forEach, anyTrueR, unnestR} from "../../common/common";
3+
import {pick, forEach, anyTrueR, unnestR, tail} from "../../common/common";
44
import {kebobString} from "../../common/strings";
55
import {ViewConfig} from "../../view/interface";
66
import {Ng1ViewDeclaration} from "../interface";
77
import {ViewService} from "../../view/view";
8-
import {isInjectable, isDefined, isString, isObject} from "../../common/predicates";
8+
import {isArray, isInjectable, isDefined, isString, isObject} from "../../common/predicates";
99
import {services} from "../../common/coreservices";
1010
import {trace} from "../../common/trace";
1111
import {PathNode} from "../../path/node";
1212
import {TemplateFactory} from "../templateFactory";
1313
import {ResolveContext} from "../../resolve/resolveContext";
14+
import {Resolvable} from "../../resolve/resolvable";
1415

1516
export const ng1ViewConfigFactory = (node, view) => new Ng1ViewConfig(node, view);
1617

@@ -111,11 +112,11 @@ export class Ng1ViewConfig implements ViewConfig {
111112
if (!this.hasTemplate())
112113
throw new Error(`No template configuration specified for '${this.viewDecl.$uiViewName}@${this.viewDecl.$uiViewContextAnchor}'`);
113114

114-
let injector = this.node.resolveContext;
115+
let context = this.node.resolveContext;
115116
let params = this.node.paramValues;
116117
let promises: any = {
117-
template: $q.when(this.getTemplate(params, new TemplateFactory(), injector)),
118-
controller: $q.when(this.getController(injector))
118+
template: $q.when(this.getTemplate(params, new TemplateFactory(), context)),
119+
controller: $q.when(this.getController(context))
119120
};
120121

121122
return $q.all(promises).then((results) => {
@@ -134,18 +135,21 @@ export class Ng1ViewConfig implements ViewConfig {
134135
return !!(this.viewDecl.template || this.viewDecl.templateUrl || this.viewDecl.templateProvider);
135136
}
136137

137-
getTemplate(params, $factory, injector: ResolveContext) {
138-
return $factory.fromConfig(this.viewDecl, params, injector.invokeLater.bind(injector));
138+
getTemplate(params, $factory, context: ResolveContext) {
139+
return $factory.fromConfig(this.viewDecl, params, context);
139140
}
140141

141142
/**
142143
* Gets the controller for a view configuration.
143144
*
144145
* @returns {Function|Promise.<Function>} Returns a controller, or a promise that resolves to a controller.
145146
*/
146-
getController(injector: ResolveContext) {
147-
//* @param {Object} locals A context object from transition.context() to invoke a function in the correct context
147+
getController(context: ResolveContext): (String|Function|Promise<Function|String>) {
148148
let provider = this.viewDecl.controllerProvider;
149-
return isInjectable(provider) ? injector.invokeLater(provider, {}) : this.viewDecl.controller;
149+
if (!isInjectable(provider)) return this.viewDecl.controller;
150+
let deps = services.$injector.annotate(provider);
151+
let providerFn = isArray(provider) ? tail(<any> provider) : provider;
152+
let resolvable = new Resolvable("", <any> providerFn, deps);
153+
return resolvable.get(context);
150154
}
151155
}

src/ng1/templateFactory.ts

+12-8
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
/** @module view */ /** for typedoc */
2-
import {isDefined, isFunction} from "../common/predicates";
2+
import {isArray, isDefined, isFunction} from "../common/predicates";
33
import {services} from "../common/coreservices";
44
import {Ng1ViewDeclaration} from "./interface";
5-
import {IInjectable} from "../common/common";
5+
import {IInjectable, tail} from "../common/common";
6+
import {ResolveContext} from "../resolve/resolveContext";
7+
import {Resolvable} from "../resolve/resolvable";
68

79
/**
810
* Service which manages loading of templates from a ViewConfig.
@@ -16,17 +18,16 @@ export class TemplateFactory {
1618
* that is defined is used to create the template:
1719
*
1820
* @param params Parameters to pass to the template function.
19-
* @param injectFn Function to which an injectable function may be passed.
20-
* If templateProvider is defined, this injectFn will be used to invoke it.
21+
* @param context The resolve context associated with the template's view
2122
*
2223
* @return {string|object} The template html as a string, or a promise for
2324
* that string,or `null` if no template is configured.
2425
*/
25-
fromConfig(config: Ng1ViewDeclaration, params: any, injectFn: Function) {
26+
fromConfig(config: Ng1ViewDeclaration, params: any, context: ResolveContext) {
2627
return (
2728
isDefined(config.template) ? this.fromString(config.template, params) :
2829
isDefined(config.templateUrl) ? this.fromUrl(config.templateUrl, params) :
29-
isDefined(config.templateProvider) ? this.fromProvider(config.templateProvider, params, injectFn) :
30+
isDefined(config.templateProvider) ? this.fromProvider(config.templateProvider, params, context) :
3031
null
3132
);
3233
};
@@ -67,7 +68,10 @@ export class TemplateFactory {
6768
* @return {string|Promise.<string>} The template html as a string, or a promise
6869
* for that string.
6970
*/
70-
fromProvider(provider: IInjectable, params: any, injectFn: Function) {
71-
return injectFn(provider);
71+
fromProvider(provider: IInjectable, params: any, context: ResolveContext) {
72+
let deps = services.$injector.annotate(provider);
73+
let providerFn = isArray(provider) ? tail(<any[]> provider) : provider;
74+
let resolvable = new Resolvable("", <Function> providerFn, deps);
75+
return resolvable.get(context);
7276
};
7377
}

src/ng2/directives/uiView.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,9 @@ export class UiView {
180180
if (!config) return;
181181

182182
// Map resolves to "useValue providers"
183-
let rc = config.node.resolveContext;
184-
let resolvables = rc.getResolvables();
185-
let rawProviders = Object.keys(resolvables).map(key => provide(key, { useValue: resolvables[key].data }));
183+
let context = config.node.resolveContext;
184+
let resolvables = context.getTokens().map(token => context.getResolvable(token)).filter(r => r.resolved);
185+
let rawProviders = resolvables.map(r => ({ provide: r.token, useValue: r.data }));
186186
rawProviders.push(provide(UiView.PARENT_INJECT, { useValue: { context: config.viewDecl.$context, fqn: uiViewData.fqn } }));
187187

188188
// Get the component class from the view declaration. TODO: allow promises?

src/path/pathFactory.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,12 @@ export class PathFactory {
145145
*
146146
* @param path a path of [[PathNode]]s
147147
* @param predicate a [[Predicate]] fn that matches [[PathNode]]s
148+
* @returns a subpath up to the matching node, or undefined if no match is found
148149
*/
149150
static subPath(path: PathNode[], predicate: Predicate<PathNode>): PathNode[] {
150151
let node = find(path, predicate);
151152
let elementIdx = path.indexOf(node);
152-
if (elementIdx === -1) throw new Error("The path does not contain a PathNode matching the predicate");
153-
return path.slice(0, elementIdx + 1);
153+
return elementIdx === -1 ? undefined : path.slice(0, elementIdx + 1);
154154
}
155155

156156
/** Gets the raw parameter values from a path */

src/resolve/interface.ts

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ export interface IOptions1 {
1212

1313
// Defines the available policies and their ordinals.
1414
export enum ResolvePolicy {
15-
JIT, // JIT resolves are resolved just-in-time, right before an injected function that depends on them is invoked.
1615
LAZY, // Lazy resolves are resolved before their state is entered.
1716
EAGER // Eager resolves are resolved before the transition starts.
1817
}

0 commit comments

Comments
 (0)