diff --git a/packages/@ember/-internals/routing/lib/system/router.ts b/packages/@ember/-internals/routing/lib/system/router.ts index 351d8d84d40..b2466ece517 100644 --- a/packages/@ember/-internals/routing/lib/system/router.ts +++ b/packages/@ember/-internals/routing/lib/system/router.ts @@ -53,7 +53,7 @@ function defaultDidTransition(this: EmberRouter, infos: PrivateRouteInfo[]) { once(this, this.trigger, 'didTransition'); if (DEBUG) { - if (get(this, 'namespace').LOG_TRANSITIONS) { + if (this.namespace.LOG_TRANSITIONS) { // eslint-disable-next-line no-console console.log(`Transitioned into '${EmberRouter._routePath(infos)}'`); } @@ -69,7 +69,7 @@ function defaultWillTransition( once(this, this.trigger, 'willTransition', transition); if (DEBUG) { - if (get(this, 'namespace').LOG_TRANSITIONS) { + if (this.namespace.LOG_TRANSITIONS) { // eslint-disable-next-line no-console console.log( `Preparing to transition from '${EmberRouter._routePath( @@ -156,12 +156,12 @@ class EmberRouter extends EmberObject { _qpUpdates = new Set(); _queuedQPChanges: { [key: string]: unknown } = {}; - _bucketCache: BucketCache | undefined; + _bucketCache: BucketCache; _toplevelView: OutletView | null = null; _handledErrors = new Set(); _engineInstances: { [name: string]: { [id: string]: EngineInstance } } = Object.create(null); _engineInfoByRoute = Object.create(null); - _routerService: RouterService | undefined; + _routerService: RouterService; _slowTransitionTimer: unknown; @@ -169,11 +169,15 @@ class EmberRouter extends EmberObject { super(...arguments); this._resetQueuedQueryParameterChanges(); - if (owner) { - this.namespace = owner.lookup('application:main'); - this._bucketCache = owner.lookup(P`-bucket-cache:main`); - this._routerService = owner.lookup('service:router'); - } + this.namespace = owner.lookup('application:main'); + + let bucketCache: BucketCache | undefined = owner.lookup(P`-bucket-cache:main`); + assert('BUG: BucketCache should always be present', bucketCache !== undefined); + this._bucketCache = bucketCache; + + let routerService: RouterService | undefined = owner.lookup('service:router'); + assert('BUG: RouterService should always be present', routerService !== undefined); + this._routerService = routerService; } _initRouterJs() { @@ -211,7 +215,7 @@ class EmberRouter extends EmberObject { route = routeOwner.lookup(fullRouteName); if (DEBUG) { - if (get(router, 'namespace.LOG_ACTIVE_GENERATION')) { + if (router.namespace.LOG_ACTIVE_GENERATION) { info(`generated -> ${fullRouteName}`, { fullName: fullRouteName }); } } @@ -303,12 +307,12 @@ class EmberRouter extends EmberObject { routeWillChange(transition: Transition) { router.trigger('routeWillChange', transition); - if (router._routerService) { - if (DEBUG) { - freezeRouteInfo(transition); - } - router._routerService.trigger('routeWillChange', transition); + + if (DEBUG) { + freezeRouteInfo(transition); } + router._routerService.trigger('routeWillChange', transition); + // in case of intermediate transition we update the current route // to make router.currentRoute.name consistent with router.currentRouteName // see https://github.com/emberjs/ember.js/issues/19449 @@ -321,12 +325,11 @@ class EmberRouter extends EmberObject { router.set('currentRoute', transition.to); once(() => { router.trigger('routeDidChange', transition); - if (router._routerService) { - if (DEBUG) { - freezeRouteInfo(transition); - } - router._routerService.trigger('routeDidChange', transition); + + if (DEBUG) { + freezeRouteInfo(transition); } + router._routerService.trigger('routeDidChange', transition); }); } @@ -384,7 +387,7 @@ class EmberRouter extends EmberObject { ); if (DEBUG) { - if (get(this, 'namespace.LOG_TRANSITIONS_INTERNAL')) { + if (this.namespace.LOG_TRANSITIONS_INTERNAL) { routerMicrolib.log = console.log.bind(console); // eslint-disable-line no-console } } @@ -422,10 +425,6 @@ class EmberRouter extends EmberObject { _hasModuleBasedResolver() { let owner = getOwner(this); - if (!owner) { - return false; - } - let resolver = get(owner, 'application.__registry__.resolver.moduleBasedResolver'); return Boolean(resolver); } @@ -588,7 +587,7 @@ class EmberRouter extends EmberObject { if (DEBUG) { let infos = this._routerMicrolib.currentRouteInfos; - if (get(this, 'namespace').LOG_TRANSITIONS) { + if (this.namespace.LOG_TRANSITIONS) { // eslint-disable-next-line no-console console.log(`Intermediate-transitioned into '${EmberRouter._routePath(infos)}'`); } @@ -722,7 +721,7 @@ class EmberRouter extends EmberObject { let rootURL = this.rootURL; let owner = getOwner(this); - if ('string' === typeof location && owner) { + if ('string' === typeof location) { let resolvedLocation = owner.lookup(`location:${location}`); if (resolvedLocation !== undefined) { diff --git a/packages/@ember/-internals/routing/tests/system/dsl_test.js b/packages/@ember/-internals/routing/tests/system/dsl_test.js index 970dadc387d..ad57892e99e 100644 --- a/packages/@ember/-internals/routing/tests/system/dsl_test.js +++ b/packages/@ember/-internals/routing/tests/system/dsl_test.js @@ -1,19 +1,23 @@ -import { setOwner } from '@ember/-internals/owner'; import EmberRouter from '../../lib/system/router'; import { buildOwner, moduleFor, AbstractTestCase } from 'internal-test-helpers'; -let Router; - moduleFor( 'Ember Router DSL', class extends AbstractTestCase { constructor() { super(); - Router = EmberRouter.extend(); + this.Router = class extends EmberRouter {}; + + this.routerInstance = new this.Router( + buildOwner({ + ownerOptions: { routable: true }, + }) + ); } teardown() { - Router = null; + this.Router = null; + this.routerInstance = null; } ['@test should fail when using a reserved route name'](assert) { @@ -23,33 +27,29 @@ moduleFor( reservedNames.forEach((reservedName) => { expectAssertion(() => { - Router = EmberRouter.extend(); + let Router = class extends this.Router {}; Router.map(function () { this.route(reservedName); }); - let router = Router.create(); - router._initRouterJs(); + new Router(buildOwner())._initRouterJs(); }, "'" + reservedName + "' cannot be used as a route name."); }); } ['@test [GH#16642] better error when using a colon in a route name']() { expectAssertion(() => { - Router = EmberRouter.extend(); - - Router.map(function () { + this.Router.map(function () { this.route('resource/:id'); }); - let router = Router.create(); - router._initRouterJs(); + this.routerInstance._initRouterJs(); }, "'resource/:id' is not a valid route name. It cannot contain a ':'. You may want to use the 'path' option instead."); } ['@test should retain resource namespace if nested with routes'](assert) { - Router = Router.map(function () { + this.Router.map(function () { this.route('bleep', function () { this.route('bloop', function () { this.route('blork'); @@ -57,7 +57,7 @@ moduleFor( }); }); - let router = Router.create(); + let router = this.routerInstance; router._initRouterJs(); assert.ok( @@ -75,16 +75,17 @@ moduleFor( } ['@test should add loading and error routes if _isRouterMapResult is true'](assert) { - Router.map(function () { + this.Router.map(function () { this.route('blork'); }); - let router = Router.create({ + this.routerInstance.reopen({ _hasModuleBasedResolver() { return true; }, }); + let router = this.routerInstance; router._initRouterJs(); assert.ok(router._routerMicrolib.recognizer.names['blork'], 'main route was created'); @@ -96,11 +97,11 @@ moduleFor( } ['@test should not add loading and error routes if _isRouterMapResult is false'](assert) { - Router.map(function () { + this.Router.map(function () { this.route('blork'); }); - let router = Router.create(); + let router = this.routerInstance; router._initRouterJs(false); assert.ok(router._routerMicrolib.recognizer.names['blork'], 'main route was created'); @@ -117,19 +118,20 @@ moduleFor( ['@test should reset namespace of loading and error routes for routes with resetNamespace']( assert ) { - Router.map(function () { + this.Router.map(function () { this.route('blork', function () { this.route('blorp'); this.route('bleep', { resetNamespace: true }); }); }); - let router = Router.create({ + this.routerInstance.reopen({ _hasModuleBasedResolver() { return true; }, }); + let router = this.routerInstance; router._initRouterJs(); assert.ok(router._routerMicrolib.recognizer.names['blork.blorp'], 'nested route was created'); @@ -167,13 +169,13 @@ moduleFor( } ['@test should throw an error when defining a route serializer outside an engine'](assert) { - Router.map(function () { + this.Router.map(function () { assert.throws(() => { this.route('posts', { serialize: function () {} }); }, /Defining a route serializer on route 'posts' outside an Engine is not allowed/); }); - Router.create()._initRouterJs(); + this.routerInstance._initRouterJs(); } } ); @@ -183,17 +185,23 @@ moduleFor( class extends AbstractTestCase { constructor() { super(); - Router = EmberRouter.extend(); + this.Router = class extends EmberRouter {}; + this.routerInstance = new this.Router( + buildOwner({ + ownerOptions: { routable: true }, + }) + ); } teardown() { - Router = null; + this.Router = null; + this.routerInstance = null; } ['@test should allow mounting of engines'](assert) { assert.expect(3); - Router = Router.map(function () { + this.Router.map(function () { this.route('bleep', function () { this.route('bloop', function () { this.mount('chat'); @@ -201,12 +209,7 @@ moduleFor( }); }); - let engineInstance = buildOwner({ - ownerOptions: { routable: true }, - }); - - let router = Router.create(); - setOwner(router, engineInstance); + let router = this.routerInstance; router._initRouterJs(); assert.ok( @@ -226,7 +229,7 @@ moduleFor( ['@test should allow mounting of engines at a custom path'](assert) { assert.expect(1); - Router = Router.map(function () { + this.Router.map(function () { this.route('bleep', function () { this.route('bloop', function () { this.mount('chat', { path: 'custom-chat' }); @@ -234,12 +237,7 @@ moduleFor( }); }); - let engineInstance = buildOwner({ - ownerOptions: { routable: true }, - }); - - let router = Router.create(); - setOwner(router, engineInstance); + let router = this.routerInstance; router._initRouterJs(); assert.deepEqual( @@ -254,7 +252,7 @@ moduleFor( ['@test should allow aliasing of engine names with `as`'](assert) { assert.expect(1); - Router = Router.map(function () { + this.Router.map(function () { this.route('bleep', function () { this.route('bloop', function () { this.mount('chat', { as: 'blork' }); @@ -262,12 +260,7 @@ moduleFor( }); }); - let engineInstance = buildOwner({ - ownerOptions: { routable: true }, - }); - - let router = Router.create(); - setOwner(router, engineInstance); + let router = this.routerInstance; router._initRouterJs(); assert.deepEqual( @@ -280,22 +273,17 @@ moduleFor( } ['@test should add loading and error routes to a mount if _isRouterMapResult is true'](assert) { - Router.map(function () { + this.Router.map(function () { this.mount('chat'); }); - let engineInstance = buildOwner({ - ownerOptions: { routable: true }, - }); - - let router = Router.create({ + this.routerInstance.reopen({ _hasModuleBasedResolver() { return true; }, }); - setOwner(router, engineInstance); - router._initRouterJs(); - + this.routerInstance._initRouterJs(); + let router = this.routerInstance; assert.ok(router._routerMicrolib.recognizer.names['chat'], 'main route was created'); assert.ok(router._routerMicrolib.recognizer.names['chat_loading'], 'loading route was added'); assert.ok(router._routerMicrolib.recognizer.names['chat_error'], 'error route was added'); @@ -304,21 +292,17 @@ moduleFor( ['@test should add loading and error routes to a mount alias if _isRouterMapResult is true']( assert ) { - Router.map(function () { + this.Router.map(function () { this.mount('chat', { as: 'shoutbox' }); }); - let engineInstance = buildOwner({ - ownerOptions: { routable: true }, - }); - - let router = Router.create({ + this.routerInstance.reopen({ _hasModuleBasedResolver() { return true; }, }); - setOwner(router, engineInstance); - router._initRouterJs(); + this.routerInstance._initRouterJs(); + let router = this.routerInstance; assert.ok(router._routerMicrolib.recognizer.names['shoutbox'], 'main route was created'); assert.ok( @@ -331,16 +315,11 @@ moduleFor( ['@test should not add loading and error routes to a mount if _isRouterMapResult is false']( assert ) { - Router.map(function () { + this.Router.map(function () { this.mount('chat'); }); - let engineInstance = buildOwner({ - ownerOptions: { routable: true }, - }); - - let router = Router.create(); - setOwner(router, engineInstance); + let router = this.routerInstance; router._initRouterJs(false); assert.ok(router._routerMicrolib.recognizer.names['chat'], 'main route was created'); @@ -357,24 +336,20 @@ moduleFor( ['@test should reset namespace of loading and error routes for mounts with resetNamespace']( assert ) { - Router.map(function () { + this.Router.map(function () { this.route('news', function () { this.mount('chat'); this.mount('blog', { resetNamespace: true }); }); }); - let engineInstance = buildOwner({ - ownerOptions: { routable: true }, - }); - - let router = Router.create({ + this.routerInstance.reopen({ _hasModuleBasedResolver() { return true; }, }); - setOwner(router, engineInstance); - router._initRouterJs(); + this.routerInstance._initRouterJs(); + let router = this.routerInstance; assert.ok(router._routerMicrolib.recognizer.names['news.chat'], 'nested route was created'); assert.ok( diff --git a/packages/@ember/-internals/routing/tests/system/router_test.js b/packages/@ember/-internals/routing/tests/system/router_test.js index 544e8dc2fc2..8a82387e405 100644 --- a/packages/@ember/-internals/routing/tests/system/router_test.js +++ b/packages/@ember/-internals/routing/tests/system/router_test.js @@ -1,4 +1,3 @@ -import { setOwner } from '@ember/-internals/owner'; import HashLocation from '../../lib/location/hash_location'; import HistoryLocation from '../../lib/location/history_location'; import AutoLocation from '../../lib/location/auto_location'; @@ -8,12 +7,11 @@ import { runDestroy, buildOwner, moduleFor, AbstractTestCase } from 'internal-te let owner; -function createRouter(settings, options = {}) { - let CustomRouter = Router.extend(); - let router = CustomRouter.create(settings); - - if (!options.skipOwner) { - setOwner(router, owner); +function createRouter({ settings = {}, options = {} } = {}) { + let CustomRouter = class extends Router {}; + let router = new CustomRouter(owner); + for (let setting in settings) { + router[setting] = settings[setting]; } if (!options.disableSetup) { @@ -42,12 +40,6 @@ moduleFor( owner = null; } - ['@test can create a router without an owner'](assert) { - createRouter(undefined, { disableSetup: true, skipOwner: true }); - - assert.ok(true, 'no errors were thrown when creating without a container'); - } - ['@test [GH#15237] EmberError is imported correctly'](assert) { // If we get the right message it means Error is being imported correctly. assert.throws(function () { @@ -56,27 +48,27 @@ moduleFor( } ['@test should not create a router.js instance upon init'](assert) { - let router = createRouter(undefined, { disableSetup: true }); + let router = createRouter({ options: { disableSetup: true } }); assert.ok(!router._routerMicrolib); } ['@test should create a router.js instance after setupRouter'](assert) { - let router = createRouter(undefined, { disableSetup: false }); + let router = createRouter({ options: { disableSetup: false } }); assert.ok(router._didSetupRouter); assert.ok(router._routerMicrolib); } ['@test should return false if setupRouter is called multiple times'](assert) { - let router = createRouter(undefined, { disableSetup: true }); + let router = createRouter({ options: { disableSetup: true } }); assert.ok(router.setupRouter()); assert.notOk(router.setupRouter()); } ['@test should not reify location until setupRouter is called'](assert) { - let router = createRouter(undefined, { disableSetup: true }); + let router = createRouter({ options: { disableSetup: true } }); assert.equal(typeof router.location, 'string', 'location is specified as a string'); router.setupRouter(); @@ -95,8 +87,11 @@ moduleFor( ['@test should instantiate its location with its `rootURL`'](assert) { let router = createRouter({ - rootURL: '/rootdir/', + settings: { + rootURL: '/rootdir/', + }, }); + let location = router.get('location'); assert.equal(location.get('rootURL'), '/rootdir/'); @@ -123,8 +118,10 @@ moduleFor( location.history = null; createRouter({ - location: 'auto', - rootURL: '/rootdir/', + settings: { + location: 'auto', + rootURL: '/rootdir/', + }, }); } @@ -200,8 +197,10 @@ moduleFor( }; createRouter({ - location: 'auto', - rootURL: '/rootdir/', + settings: { + location: 'auto', + rootURL: '/rootdir/', + }, }); } @@ -209,9 +208,11 @@ moduleFor( assert.expect(2); let router = createRouter({ - _doURLTransition(routerJsMethod, url) { - assert.equal(routerJsMethod, 'handleURL'); - assert.equal(url, '/foo/bar?time=morphin'); + settings: { + _doURLTransition(routerJsMethod, url) { + assert.equal(routerJsMethod, 'handleURL'); + assert.equal(url, '/foo/bar?time=morphin'); + }, }, }); @@ -299,7 +300,7 @@ moduleFor( } ['@test computed url when location is a string should not crash'](assert) { - let router = createRouter(undefined, { disableSetup: true }); + let router = createRouter({ options: { disableSetup: true } }); assert.equal(router.url, undefined); } }