diff --git a/app/controllers/route-tree.js b/app/controllers/route-tree.js index 18bd1f9021..e30567e398 100644 --- a/app/controllers/route-tree.js +++ b/app/controllers/route-tree.js @@ -25,6 +25,9 @@ export default class RouteTreeController extends Controller { 'searchValue' ) get filtered() { + if (!Array.isArray(this.model)) { + return []; + } return this.model.filter((routeItem) => { let currentRoute = this.currentRoute; let hideRoutes = this.get('options.hideRoutes'); diff --git a/app/routes/route-tree.js b/app/routes/route-tree.js index c82a4b2402..e81cda1785 100644 --- a/app/routes/route-tree.js +++ b/app/routes/route-tree.js @@ -25,6 +25,10 @@ export default class RouteTreeRoute extends TabRoute { } setTree(options) { + if (options.error) { + set(this, 'controller.model', options); + return; + } let routeArray = topSort(options.tree); set(this, 'controller.model', routeArray); } diff --git a/app/templates/route-tree.hbs b/app/templates/route-tree.hbs index c11f63046f..2226b96f43 100644 --- a/app/templates/route-tree.hbs +++ b/app/templates/route-tree.hbs @@ -7,6 +7,13 @@ {{/in-element}} {{/if}} +{{#if this.model.error}} +

+ Routes could not be loaded. + {{this.model.error}} +

+{{/if}} + @@ -36,4 +43,4 @@ - \ No newline at end of file + diff --git a/ember_debug/route-debug.js b/ember_debug/route-debug.js index f7a0e1ddfd..9cdfea5c7f 100644 --- a/ember_debug/route-debug.js +++ b/ember_debug/route-debug.js @@ -5,7 +5,8 @@ import classify from 'ember-debug/utils/classify'; import dasherize from 'ember-debug/utils/dasherize'; import Ember from 'ember-debug/utils/ember'; -import { later } from 'ember-debug/utils/ember/runloop'; +import { _backburner, later } from 'ember-debug/utils/ember/runloop'; +import bound from 'ember-debug/utils/bound-method'; const { hasOwnProperty } = Object.prototype; @@ -15,32 +16,35 @@ export default class RouteDebug extends DebugPort { super.init(); this.__currentURL = this.currentURL; this.__currentRouter = this.router; - this.observer = setInterval(() => { - if (this.__currentURL !== this.currentURL) { - this.sendCurrentRoute(); - this.__currentURL = this.currentURL; - } - if (this.__currentRouter !== this.router) { - this._cachedRouteTree = null; - this.__currentRouter = this.router; - } - }, 150); + _backburner.on('end', bound(this, this.checkForUpdate)); + } + + checkForUpdate() { + if (this.__currentURL !== this.currentURL) { + this.sendCurrentRoute(); + this.__currentURL = this.currentURL; + } + if (this.__currentRouter !== this.router) { + this._cachedRouteTree = null; + this.__currentRouter = this.router; + } } willDestroy() { - clearInterval(this.observer); + _backburner.off('end', bound(this, this.checkForUpdate)); super.willDestroy(); } get router() { + if ( + this.namespace?.owner.isDestroyed || + this.namespace?.owner.isDestroying + ) { + return null; + } return this.namespace?.owner.lookup('router:main'); } - get applicationController() { - const container = this.namespace?.owner; - return container.lookup('controller:application'); - } - get currentPath() { return this.namespace?.owner.router.currentPath; } @@ -73,7 +77,13 @@ export default class RouteDebug extends DebugPort { } get routeTree() { - if (!this._cachedRouteTree) { + if ( + this.namespace?.owner.isDestroyed || + this.namespace?.owner.isDestroying + ) { + return null; + } + if (!this._cachedRouteTree && this.router) { const router = this.router; const routerLib = router._routerMicrolib || router.router; let routeNames = routerLib.recognizer.names; @@ -91,8 +101,14 @@ export default class RouteDebug extends DebugPort { } sendTree() { - const routeTree = this.routeTree; - this.sendMessage('routeTree', { tree: routeTree }); + let routeTree; + let error; + try { + routeTree = this.routeTree; + } catch (e) { + error = e.message; + } + this.sendMessage('routeTree', { tree: routeTree, error }); } getClassName(name, type) { @@ -113,7 +129,7 @@ export default class RouteDebug extends DebugPort { } if (className === fullName) { // full name returned as is - this resolver does not look for the module. - className = className.replace(new RegExp(`^${type}\:`), ''); + className = className.replace(new RegExp(`^${type}:`), ''); } else if (className) { // Module exists and found className = className.replace( @@ -202,7 +218,13 @@ function buildSubTree(routeTree, route) { controllerClassName = '(unresolved)'; templateName = '(unresolved)'; } else { - controllerName = routeHandler.controllerName || routeHandler.routeName; + const get = + routeHandler.get || + function (prop) { + return this[prop]; + }; + controllerName = + get.call(routeHandler, 'controllerName') || routeHandler.routeName; controllerFactory = owner.factoryFor ? owner.factoryFor(`controller:${controllerName}`) : owner._lookupFactory(`controller:${controllerName}`);