Skip to content

Commit

Permalink
Make router service passive
Browse files Browse the repository at this point in the history
  • Loading branch information
Ravenstine authored and Ben Titcomb committed Feb 12, 2021
1 parent 7c39e15 commit 7344cd3
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 38 deletions.
50 changes: 12 additions & 38 deletions packages/@ember/-internals/routing/lib/services/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,12 @@ import { assert } from '@ember/debug';
import { readOnly } from '@ember/object/computed';
import { assign } from '@ember/polyfills';
import Service from '@ember/service';
import { DEBUG } from '@glimmer/env';
import { consumeTag, tagFor } from '@glimmer/validator';
import { Transition } from 'router_js';
import EmberRouter, { QueryParam } from '../system/router';
import { extractRouteArgs, resemblesURL, shallowEqual } from '../utils';

const ROUTER = symbol('ROUTER') as string;

let freezeRouteInfo: Function;
if (DEBUG) {
freezeRouteInfo = (transition: Transition) => {
if (transition.from !== null && !Object.isFrozen(transition.from)) {
Object.freeze(transition.from);
}

if (transition.to !== null && !Object.isFrozen(transition.to)) {
Object.freeze(transition.to);
}
};
}

function cleanURL(url: string, rootURL: string) {
if (rootURL === '/') {
return url;
Expand All @@ -34,6 +19,17 @@ function cleanURL(url: string, rootURL: string) {
return url.substr(rootURL.length, url.length);
}

function getRouter(owner: Owner): EmberRouter | null {
try {
return owner.lookup('router:main', { instantiate: false }) || null;
} catch (error) {
if (error.message !== 'Could not create factory') {
throw error;
}
return null;
}
}

/**
The Router service is the public API that provides access to the router.
Expand Down Expand Up @@ -72,32 +68,10 @@ export default class RouterService extends Service {
return router;
}
const owner = getOwner(this) as Owner;
router = owner.lookup('router:main') as EmberRouter;
router.setupRouter();
router = getRouter(owner) as EmberRouter | null;
return (this[ROUTER] = router);
}

constructor(owner: Owner) {
super(owner);

const router = owner.lookup('router:main') as EmberRouter;

router.on('routeWillChange', (transition: Transition) => {
if (DEBUG) {
freezeRouteInfo(transition);
}
this.trigger('routeWillChange', transition);
});

router.on('routeDidChange', (transition: Transition) => {
if (DEBUG) {
freezeRouteInfo(transition);
}

this.trigger('routeDidChange', transition);
});
}

/**
Transition the application into another route. The route may
be either a single route or route path:
Expand Down
40 changes: 40 additions & 0 deletions packages/@ember/-internals/routing/lib/system/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { OutletState as GlimmerOutletState, OutletView } from '@ember/-internals
import { computed, get, notifyPropertyChange, set } from '@ember/-internals/metal';
import { FactoryClass, getOwner, Owner } from '@ember/-internals/owner';
import { BucketCache } from '@ember/-internals/routing';
import RouterService from '@ember/-internals/routing/lib/services/router';
import { A as emberA, Evented, Object as EmberObject, typeOf } from '@ember/-internals/runtime';
import Controller from '@ember/controller';
import { assert, deprecate, info } from '@ember/debug';
Expand All @@ -23,6 +24,7 @@ import Route, {
ROUTER_EVENT_DEPRECATIONS,
} from './route';
import RouterState from './router_state';

/**
@module @ember/routing
*/
Expand Down Expand Up @@ -78,6 +80,30 @@ function defaultWillTransition(
}
}

let freezeRouteInfo: Function;
if (DEBUG) {
freezeRouteInfo = (transition: Transition) => {
if (transition.from !== null && !Object.isFrozen(transition.from)) {
Object.freeze(transition.from);
}

if (transition.to !== null && !Object.isFrozen(transition.to)) {
Object.freeze(transition.to);
}
};
}

function getRouterService(owner: Owner): RouterService | null {
try {
return owner.lookup('service:router', { instantiate: false }) || null;
} catch (error) {
if (error.message !== 'Could not create factory') {
throw error;
}
return null;
}
}

interface RenderOutletState {
name: string;
outlet: string;
Expand Down Expand Up @@ -286,12 +312,26 @@ class EmberRouter extends EmberObject {

routeWillChange(transition: Transition) {
router.trigger('routeWillChange', transition);
const routerService: RouterService | null = getRouterService(owner);
if (routerService) {
if (DEBUG) {
freezeRouteInfo(transition);
}
routerService.trigger('routeWillChange', transition);
}
}

routeDidChange(transition: Transition) {
router.set('currentRoute', transition.to);
once(() => {
router.trigger('routeDidChange', transition);
const routerService: RouterService | null = getRouterService(owner);
if (routerService) {
if (DEBUG) {
freezeRouteInfo(transition);
}
routerService.trigger('routeDidChange', transition);
}
});
}

Expand Down
16 changes: 16 additions & 0 deletions packages/ember/tests/routing/router_service_test/basic_test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Route, NoneLocation } from '@ember/-internals/routing';
import { set } from '@ember/-internals/metal';
import { RouterTestCase, moduleFor } from 'internal-test-helpers';
import { inject as injectService } from '@ember/service';

moduleFor(
'Router Service - main',
Expand Down Expand Up @@ -150,5 +151,20 @@ moduleFor(
assert.ok(location instanceof NoneLocation);
});
}

['@test RouterService can be injected into router and accessed on init'](assert) {
assert.expect(1);

this.router.reopen({
routerService: injectService('router'),
init() {
this.routerService.one('routeDidChange', () => {
assert.ok(true, 'routeDidChange event listener called');
});
},
});

return this.visit('/');
}
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,36 @@ moduleFor(
assert.expect(5);
assert.equal(this.routerService.get('currentRouteName'), null);
assert.equal(this.routerService.get('currentURL'), null);
assert.equal(this.routerService.get('location'), null);
assert.equal(this.routerService.get('rootURL'), null);
assert.equal(this.routerService.get('currentRoute'), null);
}

['@test RouterService properties of router can be accessed with default when router is present'](
assert
) {
assert.expect(5);
let router = this.owner.lookup('router:main');
router.setupRouter();
assert.equal(this.routerService.get('currentRouteName'), null);
assert.equal(this.routerService.get('currentURL'), null);
assert.ok(this.routerService.get('location') instanceof NoneLocation);
assert.equal(this.routerService.get('rootURL'), '/');
assert.equal(this.routerService.get('currentRoute'), null);
}

['@test RouterService#urlFor returns url'](assert) {
let router = this.owner.lookup('router:main');
router.setupRouter();
assert.equal(this.routerService.urlFor('parent.child'), '/child');
}

['@test RouterService#transitionTo with basic route'](assert) {
assert.expect(2);

let componentInstance;
let router = this.owner.lookup('router:main');
router.setupRouter();

this.addTemplate('parent.index', '{{foo-bar}}');

Expand Down Expand Up @@ -90,6 +107,8 @@ moduleFor(
}

['@test RouterService#recognize recognize returns routeInfo'](assert) {
let router = this.owner.lookup('router:main');
router.setupRouter();
let routeInfo = this.routerService.recognize('/dynamic-with-child/123/1?a=b');
assert.ok(routeInfo);
let { name, localName, parent, child, params, queryParams, paramNames } = routeInfo;
Expand Down

0 comments on commit 7344cd3

Please sign in to comment.