Skip to content

Commit

Permalink
BREAKING CHANGE: (CoreServices) Move location and locationConfig
Browse files Browse the repository at this point in the history
…from `services` to `UIRouter.locationService` and `UIRouter.locationConfig`.

The core `services` object is a mutable object which each framework was monkey patching.
This change removes the requirement to monkey patch a global mutable object.
Instead, framework implementors should pass the `LocationServices` and `LocationConfig` implementations into the `UIRouter` constructor.

### End Users

End users who were accessing `services.location` or `services.locationConfig` should access these off the `UIRouter` instance instead.
  • Loading branch information
christopherthielen committed Dec 20, 2016
1 parent 9d316a7 commit 029fb00
Show file tree
Hide file tree
Showing 9 changed files with 34 additions and 36 deletions.
21 changes: 10 additions & 11 deletions src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
* @module core
*/ /** */
import { UrlMatcherFactory } from "./url/urlMatcherFactory";
import { UrlRouterProvider } from "./url/urlRouter";
import { UrlRouter } from "./url/urlRouter";
import { UrlRouterProvider, UrlRouter } from "./url/urlRouter";
import { TransitionService } from "./transition/transitionService";
import { ViewService } from "./view/view";
import { StateRegistry } from "./state/stateRegistry";
Expand All @@ -14,7 +13,7 @@ import { UIRouterPlugin, Disposable } from "./interface";
import { values, removeFrom } from "./common/common";
import { isFunction } from "./common/predicates";
import { UrlService } from "./url/urlService";
import { services, LocationServices, LocationConfig } from "./common/coreservices";
import { LocationServices, LocationConfig } from "./common/coreservices";

/** @hidden */
let _routerInstance = 0;
Expand Down Expand Up @@ -50,13 +49,7 @@ export class UIRouter {

stateService = new StateService(this);

get urlService(): LocationServices {
return services.location;
}

get urlConfig(): LocationConfig {
return services.locationConfig;
}
urlService: UrlService = new UrlService(this);

private _disposables: Disposable[] = [];

Expand Down Expand Up @@ -89,7 +82,11 @@ export class UIRouter {
});
}

constructor() {
constructor(
public locationService: LocationServices = UrlService.locationServiceStub,
public locationConfig: LocationConfig = UrlService.locationConfigStub
) {

this.viewService._pluginapi._rootViewContext(this.stateRegistry.root());
this.globals.$current = this.stateRegistry.root();
this.globals.current = this.globals.$current.self;
Expand All @@ -98,6 +95,8 @@ export class UIRouter {
this.disposable(this.urlRouterProvider);
this.disposable(this.urlRouter);
this.disposable(this.stateRegistry);
this.disposable(locationService);
this.disposable(locationConfig);
}

/** @hidden */
Expand Down
7 changes: 4 additions & 3 deletions src/state/stateService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
* @coreapi
* @module state
*/ /** */
import { extend, defaults, silentRejection, silenceUncaughtInPromise, removeFrom, noop } from "../common/common";
import {
extend, defaults, silentRejection, silenceUncaughtInPromise, removeFrom, noop, createProxyFunctions
} from "../common/common";
import {isDefined, isObject, isString} from "../common/predicates";
import {Queue} from "../common/queue";
import {services} from "../common/coreservices";
Expand All @@ -24,7 +26,6 @@ import {ParamsOrArray} from "../params/interface";
import {Param} from "../params/param";
import {Glob} from "../common/glob";
import {HrefOptions} from "./interface";
import {bindFunctions} from "../common/common";
import {Globals} from "../globals";
import {UIRouter} from "../router";
import {UIInjector} from "../interface";
Expand Down Expand Up @@ -74,7 +75,7 @@ export class StateService {
constructor(private router: UIRouter) {
let getters = ['current', '$current', 'params', 'transition'];
let boundFns = Object.keys(StateService.prototype).filter(key => getters.indexOf(key) === -1);
bindFunctions(StateService.prototype, this, this, boundFns);
createProxyFunctions(StateService.prototype, this, this, boundFns);
}

/** @internalapi */
Expand Down
4 changes: 2 additions & 2 deletions src/transition/transitionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { registerLazyLoadHook } from "../hooks/lazyLoad";
import { TransitionEventType } from "./transitionEventType";
import { TransitionHook, GetResultHandler, GetErrorHandler } from "./transitionHook";
import { isDefined } from "../common/predicates";
import { removeFrom, values, bindFunctions } from "../common/common";
import { removeFrom, values, createProxyFunctions } from "../common/common";
import { Disposable } from "../interface"; // has or is using

/**
Expand Down Expand Up @@ -149,7 +149,7 @@ export class TransitionService implements IHookRegistry, Disposable {
constructor(private _router: UIRouter) {
this.$view = _router.viewService;
this._deregisterHookFns = <any> {};
this._pluginapi = <TransitionServicePluginAPI> bindFunctions(this, {}, this, [
this._pluginapi = <TransitionServicePluginAPI> createProxyFunctions(this, {}, this, [
'_definePathType',
'_defineEvent',
'_getPathTypes',
Expand Down
17 changes: 8 additions & 9 deletions src/url/urlRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @coreapi
* @module url
*/ /** for typedoc */
import { extend, bindFunctions, IInjectable, removeFrom } from "../common/common";
import { extend, IInjectable, removeFrom, createProxyFunctions } from "../common/common";
import { isFunction, isString, isDefined, isArray } from "../common/predicates";
import { UrlMatcher } from "./urlMatcher";
import { services, $InjectorLike, LocationServices } from "../common/coreservices";
Expand Down Expand Up @@ -260,10 +260,10 @@ export class UrlRouterProvider implements Disposable {
* });
* ```
*
* @param defer Indicates whether to defer location change interception. Passing
* no parameter is equivalent to `true`.
* @param defer Indicates whether to defer location change interception.
* Passing no parameter is equivalent to `true`.
*/
deferIntercept(defer) {
deferIntercept(defer?: boolean) {
if (defer === undefined) defer = true;
this.interceptDeferred = defer;
};
Expand All @@ -277,7 +277,7 @@ export class UrlRouter implements Disposable {

/** @hidden */
constructor(public router: UIRouter) {
bindFunctions(UrlRouter.prototype, this, this);
createProxyFunctions(UrlRouter.prototype, this, this);
}

/** @internalapi */
Expand Down Expand Up @@ -398,11 +398,10 @@ export class UrlRouter implements Disposable {
let url = urlMatcher.format(params);
options = options || { absolute: false };

let cfg = this.router.urlConfig;
let loc = this.router.urlService;
let isHtml5 = loc.html5Mode();
let cfg = this.router.urlService.config;
let isHtml5 = cfg.html5Mode();
if (!isHtml5 && url !== null) {
url = "#" + loc.hashPrefix() + url;
url = "#" + cfg.hashPrefix() + url;
}
url = appendBasePath(url, isHtml5, options.absolute, cfg.baseHref());

Expand Down
11 changes: 4 additions & 7 deletions src/vanilla/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import {isArray} from "../common/index";
import { LocationServices, LocationConfig, services } from "../common/coreservices";
import { UIRouter } from "../router";
import { extend, bindFunctions } from "../common/common";

const beforeAfterSubstr = (char: string) => (str: string): string[] => {
if (!str) return ["", ""];
Expand Down Expand Up @@ -35,21 +34,19 @@ export const getParams = (queryString: string): any =>

export function locationPluginFactory(
name: string,
isHtml5: boolean,
serviceClass: { new(router?: UIRouter): LocationServices },
configurationClass: { new(router?: UIRouter): LocationConfig }
configurationClass: { new(router?: UIRouter, isHtml5?: boolean): LocationConfig }
) {
return function(router: UIRouter) {
let service = new serviceClass(router);
let configuration = new configurationClass(router);
let service = router.locationService = new serviceClass(router);
let configuration = router.locationConfig = new configurationClass(router, isHtml5);

function dispose(router: UIRouter) {
router.dispose(service);
router.dispose(configuration);
}

bindFunctions(serviceClass.prototype, services.location, service);
bindFunctions(configurationClass.prototype, services.locationConfig, configuration);

return { name, service, configuration, dispose };
};
}
3 changes: 2 additions & 1 deletion test/stateRegistrySpec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { UIRouter } from "../src/router";
import { tree2Array } from "./_testUtils";
import { StateRegistry } from "../src/state/stateRegistry";
import { services } from "../src/common/coreservices";
import { TestingPlugin } from "./_testingPlugin";

let router: UIRouter = null;
let registry: StateRegistry = null;
Expand All @@ -20,6 +20,7 @@ let statetree = {
describe("StateRegistry", () => {
beforeEach(() => {
router = new UIRouter();
router.plugin(TestingPlugin);
registry = router.stateRegistry;
tree2Array(statetree, true).forEach(state => registry.register(state));
registry.stateQueue.autoFlush(router.stateService);
Expand Down
1 change: 1 addition & 0 deletions test/stateServiceSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ describe('stateService', function () {
afterEach(() => router.dispose());

beforeEach(() => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
router = new UIRouter();
router.plugin(TestingPlugin);

Expand Down
4 changes: 2 additions & 2 deletions test/vanilla.browserHistorySpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe('browserHistory implementation', () => {

it('uses history.pushState when setting a url', () => {
let service = mockHistoryObject();
expect(router.urlService.html5Mode()).toBe(true);
expect(router.urlService.config.html5Mode()).toBe(true);
let stub = spyOn(service._history, 'pushState');
router.urlRouter.push(makeMatcher('/hello/:name'), { name: 'world' }, {});
expect(stub.calls.first().args[2]).toBe('/hello/world');
Expand All @@ -53,7 +53,7 @@ describe('browserHistory implementation', () => {
});

it('returns the correct url query', () => {
expect(router.urlService.html5Mode()).toBe(true);
expect(router.urlService.config.html5Mode()).toBe(true);
return router.stateService.go('path', {urlParam: 'bar'}).then(() => {
expect(window.location.toString().includes('/path/bar')).toBe(true);
expect(window.location.toString().includes('/#/path/bar')).toBe(false);
Expand Down
2 changes: 1 addition & 1 deletion test/vanilla.hashHistorySpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('hashHistory implementation', () => {
});

it('reports html5Mode to be false', () => {
expect(router.urlService.html5Mode()).toBe(false);
expect(router.urlService.config.html5Mode()).toBe(false);
});

it('returns the correct url query', (done) => {
Expand Down

0 comments on commit 029fb00

Please sign in to comment.