ember-source 4.3.0-alpha.1 → 4.3.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/CHANGELOG.md +6 -2
  2. package/blueprints/component-addon/index.js +2 -3
  3. package/blueprints/component-class-addon/index.js +2 -3
  4. package/blueprints/controller/files/__root__/__path__/__name__.js +2 -2
  5. package/blueprints/controller/index.js +2 -4
  6. package/blueprints/route/files/__root__/__path__/__name__.js +3 -3
  7. package/blueprints/route/index.js +2 -3
  8. package/blueprints/service/files/__root__/__path__/__name__.js +2 -2
  9. package/blueprints/service/index.js +2 -4
  10. package/build-metadata.json +3 -3
  11. package/dist/dependencies/router_js.js +66 -31
  12. package/dist/ember-template-compiler.js +1250 -861
  13. package/dist/ember-template-compiler.map +1 -1
  14. package/dist/ember-testing.js +88 -56
  15. package/dist/ember-testing.map +1 -1
  16. package/dist/ember.debug.js +3712 -3159
  17. package/dist/ember.debug.map +1 -1
  18. package/dist/header/license.js +1 -1
  19. package/dist/header/loader.js +0 -1
  20. package/dist/packages/@ember/-internals/bootstrap/index.js +0 -2
  21. package/dist/packages/@ember/-internals/container/index.js +16 -11
  22. package/dist/packages/@ember/-internals/extension-support/lib/container_debug_adapter.js +3 -3
  23. package/dist/packages/@ember/-internals/extension-support/lib/data_adapter.js +52 -52
  24. package/dist/packages/@ember/-internals/glimmer/index.js +161 -125
  25. package/dist/packages/@ember/-internals/meta/lib/meta.js +67 -11
  26. package/dist/packages/@ember/-internals/metal/index.js +95 -121
  27. package/dist/packages/@ember/-internals/routing/lib/ext/controller.js +24 -12
  28. package/dist/packages/@ember/-internals/routing/lib/location/api.js +1 -0
  29. package/dist/packages/@ember/-internals/routing/lib/location/auto_location.js +3 -1
  30. package/dist/packages/@ember/-internals/routing/lib/services/router.js +117 -197
  31. package/dist/packages/@ember/-internals/routing/lib/services/routing.js +3 -1
  32. package/dist/packages/@ember/-internals/routing/lib/system/route-info.js +2 -2
  33. package/dist/packages/@ember/-internals/routing/lib/system/route.js +147 -402
  34. package/dist/packages/@ember/-internals/routing/lib/system/router.js +82 -40
  35. package/dist/packages/@ember/-internals/routing/lib/utils.js +48 -25
  36. package/dist/packages/@ember/-internals/runtime/lib/mixins/-proxy.js +1 -1
  37. package/dist/packages/@ember/-internals/runtime/lib/mixins/array.js +1 -0
  38. package/dist/packages/@ember/-internals/runtime/lib/mixins/comparable.js +4 -4
  39. package/dist/packages/@ember/-internals/runtime/lib/mixins/container_proxy.js +29 -29
  40. package/dist/packages/@ember/-internals/runtime/lib/mixins/promise_proxy.js +16 -16
  41. package/dist/packages/@ember/-internals/runtime/lib/mixins/registry_proxy.js +48 -48
  42. package/dist/packages/@ember/-internals/runtime/lib/mixins/target_action_support.js +8 -8
  43. package/dist/packages/@ember/-internals/runtime/lib/system/namespace.js +1 -2
  44. package/dist/packages/@ember/-internals/runtime/lib/type-of.js +1 -1
  45. package/dist/packages/@ember/-internals/utils/index.js +11 -9
  46. package/dist/packages/@ember/-internals/views/lib/mixins/view_support.js +2 -4
  47. package/dist/packages/@ember/-internals/views/lib/system/utils.js +2 -0
  48. package/dist/packages/@ember/application/lib/application.js +0 -2
  49. package/dist/packages/@ember/array/index.js +1 -1
  50. package/dist/packages/@ember/canary-features/index.js +2 -2
  51. package/dist/packages/@ember/controller/index.js +3 -54
  52. package/dist/packages/@ember/debug/index.js +1 -1
  53. package/dist/packages/@ember/debug/lib/deprecate.js +12 -10
  54. package/dist/packages/@ember/instrumentation/index.js +9 -13
  55. package/dist/packages/@ember/object/compat.js +16 -7
  56. package/dist/packages/@ember/polyfills/lib/assign.js +1 -0
  57. package/dist/packages/@ember/routing/router-service.js +1 -0
  58. package/dist/packages/@ember/runloop/index.js +9 -9
  59. package/dist/packages/@ember/service/index.js +6 -73
  60. package/dist/packages/@ember/string/index.js +1 -0
  61. package/dist/packages/ember/index.js +1 -2
  62. package/dist/packages/ember/version.js +1 -1
  63. package/docs/data.json +2588 -1839
  64. package/package.json +27 -27
  65. package/blueprints/component-addon/native-files/__root__/__path__/__name__.js +0 -1
  66. package/blueprints/component-class-addon/native-files/__root__/__path__/__name__.js +0 -1
  67. package/blueprints/controller/native-files/__root__/__path__/__name__.js +0 -4
  68. package/blueprints/edition-detector.js +0 -13
  69. package/blueprints/route/native-files/__root__/__path__/__name__.js +0 -11
  70. package/blueprints/route/native-files/__root__/__templatepath__/__templatename__.hbs +0 -2
  71. package/blueprints/service/native-files/__root__/__path__/__name__.js +0 -4
@@ -20,47 +20,6 @@ import { calculateCacheKey, deprecateTransitionMethods, normalizeControllerQuery
20
20
  import generateController from './generate_controller';
21
21
  export const ROUTE_CONNECTIONS = new WeakMap();
22
22
  const RENDER = symbol('render');
23
- export function defaultSerialize(model, params) {
24
- if (params.length < 1 || !model) {
25
- return;
26
- }
27
-
28
- let object = {};
29
-
30
- if (params.length === 1) {
31
- let [name] = params;
32
-
33
- if (name in model) {
34
- object[name] = get(model, name);
35
- } else if (/_id$/.test(name)) {
36
- object[name] = get(model, 'id');
37
- } else if (isProxy(model)) {
38
- object[name] = get(model, name);
39
- }
40
- } else {
41
- object = getProperties(model, params);
42
- }
43
-
44
- return object;
45
- }
46
- export function hasDefaultSerialize(route) {
47
- return route.serialize === defaultSerialize;
48
- }
49
- /**
50
- @module @ember/routing
51
- */
52
-
53
- /**
54
- The `Route` class is used to define individual routes. Refer to
55
- the [routing guide](https://guides.emberjs.com/release/routing/) for documentation.
56
-
57
- @class Route
58
- @extends EmberObject
59
- @uses ActionHandler
60
- @uses Evented
61
- @since 1.0.0
62
- @public
63
- */
64
23
 
65
24
  class Route extends EmberObject.extend(ActionHandler, Evented) {
66
25
  constructor(owner) {
@@ -77,6 +36,68 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
77
36
  this._environment = owner.lookup('-environment:main');
78
37
  }
79
38
  }
39
+ /**
40
+ A hook you can implement to convert the route's model into parameters
41
+ for the URL.
42
+ ```app/router.js
43
+ // ...
44
+ Router.map(function() {
45
+ this.route('post', { path: '/posts/:post_id' });
46
+ });
47
+ ```
48
+ ```app/routes/post.js
49
+ import Route from '@ember/routing/route';
50
+ export default class PostRoute extends Route {
51
+ model({ post_id }) {
52
+ // the server returns `{ id: 12 }`
53
+ return fetch(`/posts/${post_id}`;
54
+ }
55
+ serialize(model) {
56
+ // this will make the URL `/posts/12`
57
+ return { post_id: model.id };
58
+ }
59
+ }
60
+ ```
61
+ The default `serialize` method will insert the model's `id` into the
62
+ route's dynamic segment (in this case, `:post_id`) if the segment contains '_id'.
63
+ If the route has multiple dynamic segments or does not contain '_id', `serialize`
64
+ will return `getProperties(model, params)`
65
+ This method is called when `transitionTo` is called with a context
66
+ in order to populate the URL.
67
+ @method serialize
68
+ @param {Object} model the routes model
69
+ @param {Array} params an Array of parameter names for the current
70
+ route (in the example, `['post_id']`.
71
+ @return {Object} the serialized parameters
72
+ @since 1.0.0
73
+ @public
74
+ */
75
+
76
+
77
+ serialize(model, params) {
78
+ if (params.length < 1 || !model) {
79
+ return;
80
+ }
81
+
82
+ let object = {};
83
+
84
+ if (params.length === 1) {
85
+ let [name] = params;
86
+ assert('has name', name);
87
+
88
+ if (name in model) {
89
+ object[name] = get(model, name);
90
+ } else if (/_id$/.test(name)) {
91
+ object[name] = get(model, 'id');
92
+ } else if (isProxy(model)) {
93
+ object[name] = get(model, name);
94
+ }
95
+ } else {
96
+ object = getProperties(model, params);
97
+ }
98
+
99
+ return object;
100
+ }
80
101
  /**
81
102
  Sets the name for this route, including a fully resolved name for routes
82
103
  inside engines.
@@ -88,7 +109,9 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
88
109
 
89
110
  _setRouteName(name) {
90
111
  this.routeName = name;
91
- this.fullRouteName = getEngineRouteName(getOwner(this), name);
112
+ let owner = getOwner(this);
113
+ assert('Route is unexpectedly missing an owner', owner);
114
+ this.fullRouteName = getEngineRouteName(owner, name);
92
115
  }
93
116
  /**
94
117
  @private
@@ -106,18 +129,17 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
106
129
  if (!names.length) {
107
130
  routeInfo = dynamicParent;
108
131
  names = routeInfo && routeInfo['_names'] || [];
109
- }
132
+ } // SAFETY: Since `_qp` is protected we can't infer the type
133
+
110
134
 
111
- let qps = get(this, '_qp.qps');
135
+ let qps = get(this, '_qp').qps;
112
136
  let namePaths = new Array(names.length);
113
137
 
114
138
  for (let a = 0; a < names.length; ++a) {
115
139
  namePaths[a] = `${routeInfo.name}.${names[a]}`;
116
140
  }
117
141
 
118
- for (let i = 0; i < qps.length; ++i) {
119
- let qp = qps[i];
120
-
142
+ for (let qp of qps) {
121
143
  if (qp.scope === 'model') {
122
144
  qp.parts = namePaths;
123
145
  }
@@ -187,7 +209,9 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
187
209
 
188
210
 
189
211
  paramsFor(name) {
190
- let route = getOwner(this).lookup(`route:${name}`);
212
+ let owner = getOwner(this);
213
+ assert('Route is unexpectedly missing an owner', owner);
214
+ let route = owner.lookup(`route:${name}`);
191
215
 
192
216
  if (route === undefined) {
193
217
  return {};
@@ -198,9 +222,9 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
198
222
  let fullName = route.fullRouteName;
199
223
  let params = Object.assign({}, state.params[fullName]);
200
224
  let queryParams = getQueryParamsFor(route, state);
201
- return Object.keys(queryParams).reduce((params, key) => {
225
+ return Object.entries(queryParams).reduce((params, [key, value]) => {
202
226
  assert(`The route '${this.routeName}' has both a dynamic segment and query param with name '${key}'. Please rename one to avoid collisions.`, !params[key]);
203
- params[key] = queryParams[key];
227
+ params[key] = value;
204
228
  return params;
205
229
  }, params);
206
230
  }
@@ -301,8 +325,9 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
301
325
 
302
326
 
303
327
  _internalReset(isExiting, transition) {
304
- let controller = this.controller;
305
- controller['_qpDelegate'] = get(this, '_qp.states.inactive');
328
+ let controller = this.controller; // SAFETY: Since `_qp` is protected we can't infer the type
329
+
330
+ controller['_qpDelegate'] = get(this, '_qp').states.inactive;
306
331
  this.resetController(controller, isExiting, transition);
307
332
  }
308
333
  /**
@@ -316,148 +341,6 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
316
341
  this.activate(transition);
317
342
  this.trigger('activate', transition);
318
343
  }
319
- /**
320
- The `willTransition` action is fired at the beginning of any
321
- attempted transition with a `Transition` object as the sole
322
- argument. This action can be used for aborting, redirecting,
323
- or decorating the transition from the currently active routes.
324
- A good example is preventing navigation when a form is
325
- half-filled out:
326
- ```app/routes/contact-form.js
327
- import Route from '@ember/routing/route';
328
- import { action } from '@ember/object';
329
- export default class ContactFormRoute extends Route {
330
- @action
331
- willTransition(transition) {
332
- if (this.controller.get('userHasEnteredData')) {
333
- this.controller.displayNavigationConfirm();
334
- transition.abort();
335
- }
336
- }
337
- }
338
- ```
339
- You can also redirect elsewhere by calling
340
- `this.transitionTo('elsewhere')` from within `willTransition`.
341
- Note that `willTransition` will not be fired for the
342
- redirecting `transitionTo`, since `willTransition` doesn't
343
- fire when there is already a transition underway. If you want
344
- subsequent `willTransition` actions to fire for the redirecting
345
- transition, you must first explicitly call
346
- `transition.abort()`.
347
- To allow the `willTransition` event to continue bubbling to the parent
348
- route, use `return true;`. When the `willTransition` method has a
349
- return value of `true` then the parent route's `willTransition` method
350
- will be fired, enabling "bubbling" behavior for the event.
351
- @event willTransition
352
- @param {Transition} transition
353
- @since 1.0.0
354
- @public
355
- */
356
-
357
- /**
358
- The `didTransition` action is fired after a transition has
359
- successfully been completed. This occurs after the normal model
360
- hooks (`beforeModel`, `model`, `afterModel`, `setupController`)
361
- have resolved. The `didTransition` action has no arguments,
362
- however, it can be useful for tracking page views or resetting
363
- state on the controller.
364
- ```app/routes/login.js
365
- import Route from '@ember/routing/route';
366
- import { action } from '@ember/object';
367
- export default class LoginRoute extends Route {
368
- @action
369
- didTransition() {
370
- this.controller.get('errors.base').clear();
371
- return true; // Bubble the didTransition event
372
- }
373
- }
374
- ```
375
- @event didTransition
376
- @since 1.2.0
377
- @public
378
- */
379
-
380
- /**
381
- The `loading` action is fired on the route when a route's `model`
382
- hook returns a promise that is not already resolved. The current
383
- `Transition` object is the first parameter and the route that
384
- triggered the loading event is the second parameter.
385
- ```app/routes/application.js
386
- import Route from '@ember/routing/route';
387
- import { action } from '@ember/object';
388
- export default class ApplicationRoute extends Route {
389
- @action
390
- loading(transition, route) {
391
- let controller = this.controllerFor('foo');
392
- // The controller may not be instantiated when initially loading
393
- if (controller) {
394
- controller.currentlyLoading = true;
395
- transition.finally(function() {
396
- controller.currentlyLoading = false;
397
- });
398
- }
399
- }
400
- }
401
- ```
402
- @event loading
403
- @param {Transition} transition
404
- @param {Route} route The route that triggered the loading event
405
- @since 1.2.0
406
- @public
407
- */
408
-
409
- /**
410
- When attempting to transition into a route, any of the hooks
411
- may return a promise that rejects, at which point an `error`
412
- action will be fired on the partially-entered routes, allowing
413
- for per-route error handling logic, or shared error handling
414
- logic defined on a parent route.
415
- Here is an example of an error handler that will be invoked
416
- for rejected promises from the various hooks on the route,
417
- as well as any unhandled errors from child routes:
418
- ```app/routes/admin.js
419
- import { reject } from 'rsvp';
420
- import Route from '@ember/routing/route';
421
- import { action } from '@ember/object';
422
- export default class AdminRoute extends Route {
423
- beforeModel() {
424
- return reject('bad things!');
425
- }
426
- @action
427
- error(error, transition) {
428
- // Assuming we got here due to the error in `beforeModel`,
429
- // we can expect that error === "bad things!",
430
- // but a promise model rejecting would also
431
- // call this hook, as would any errors encountered
432
- // in `afterModel`.
433
- // The `error` hook is also provided the failed
434
- // `transition`, which can be stored and later
435
- // `.retry()`d if desired.
436
- this.transitionTo('login');
437
- }
438
- }
439
- ```
440
- `error` actions that bubble up all the way to `ApplicationRoute`
441
- will fire a default error handler that logs the error. You can
442
- specify your own global default error handler by overriding the
443
- `error` handler on `ApplicationRoute`:
444
- ```app/routes/application.js
445
- import Route from '@ember/routing/route';
446
- import { action } from '@ember/object';
447
- export default class ApplicationRoute extends Route {
448
- @action
449
- error(error, transition) {
450
- this.controllerFor('banner').displayError(error.message);
451
- }
452
- }
453
- ```
454
- @event error
455
- @param {Error} error
456
- @param {Transition} transition
457
- @since 1.0.0
458
- @public
459
- */
460
-
461
344
  /**
462
345
  This event is triggered when the router enters the route. It is
463
346
  not executed when the model for the route changes.
@@ -768,24 +651,17 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
768
651
  setup(context, transition) {
769
652
  let controllerName = this.controllerName || this.routeName;
770
653
  let definedController = this.controllerFor(controllerName, true);
771
- let controller;
654
+ let controller = definedController !== null && definedController !== void 0 ? definedController : this.generateController(controllerName); // SAFETY: Since `_qp` is protected we can't infer the type
772
655
 
773
- if (definedController) {
774
- controller = definedController;
775
- } else {
776
- controller = this.generateController(controllerName);
777
- } // Assign the route's controller so that it can more easily be
656
+ let queryParams = get(this, '_qp'); // Assign the route's controller so that it can more easily be
778
657
  // referenced in action handlers. Side effects. Side effects everywhere.
779
658
 
780
-
781
659
  if (!this.controller) {
782
- let qp = get(this, '_qp');
783
- let propNames = qp !== undefined ? get(qp, 'propertyNames') : [];
660
+ let propNames = queryParams.propertyNames;
784
661
  addQueryParamsObservers(controller, propNames);
785
662
  this.controller = controller;
786
663
  }
787
664
 
788
- let queryParams = get(this, '_qp');
789
665
  let states = queryParams.states;
790
666
  controller._qpDelegate = states.allowOverrides;
791
667
 
@@ -797,6 +673,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
797
673
  let allParams = queryParams.propertyNames;
798
674
  allParams.forEach(prop => {
799
675
  let aQp = queryParams.map[prop];
676
+ assert('expected aQp', aQp);
800
677
  aQp.values = params;
801
678
  let cacheKey = calculateCacheKey(aQp.route.fullRouteName, aQp.parts, aQp.values);
802
679
  let value = cache.lookup(cacheKey, prop, aQp.undecoratedDefaultValue);
@@ -833,71 +710,10 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
833
710
  let cacheKey = calculateCacheKey(qp.route.fullRouteName, qp.parts, qp.values);
834
711
  cache.stash(cacheKey, prop, value);
835
712
  }
836
- /**
837
- This hook is the first of the route entry validation hooks
838
- called when an attempt is made to transition into a route
839
- or one of its children. It is called before `model` and
840
- `afterModel`, and is appropriate for cases when:
841
- 1) A decision can be made to redirect elsewhere without
842
- needing to resolve the model first.
843
- 2) Any async operations need to occur first before the
844
- model is attempted to be resolved.
845
- This hook is provided the current `transition` attempt
846
- as a parameter, which can be used to `.abort()` the transition,
847
- save it for a later `.retry()`, or retrieve values set
848
- on it from a previous hook. You can also just call
849
- `this.transitionTo` to another route to implicitly
850
- abort the `transition`.
851
- You can return a promise from this hook to pause the
852
- transition until the promise resolves (or rejects). This could
853
- be useful, for instance, for retrieving async code from
854
- the server that is required to enter a route.
855
- @method beforeModel
856
- @param {Transition} transition
857
- @return {any | Promise<any>} if the value returned from this hook is
858
- a promise, the transition will pause until the transition
859
- resolves. Otherwise, non-promise return values are not
860
- utilized in any way.
861
- @since 1.0.0
862
- @public
863
- */
864
-
865
-
866
- beforeModel() {}
867
- /**
868
- This hook is called after this route's model has resolved.
869
- It follows identical async/promise semantics to `beforeModel`
870
- but is provided the route's resolved model in addition to
871
- the `transition`, and is therefore suited to performing
872
- logic that can only take place after the model has already
873
- resolved.
874
- ```app/routes/posts.js
875
- import Route from '@ember/routing/route';
876
- export default class PostsRoute extends Route {
877
- afterModel(posts, transition) {
878
- if (posts.get('length') === 1) {
879
- this.transitionTo('post.show', posts.get('firstObject'));
880
- }
881
- }
882
- }
883
- ```
884
- Refer to documentation for `beforeModel` for a description
885
- of transition-pausing semantics when a promise is returned
886
- from this hook.
887
- @method afterModel
888
- @param {Object} resolvedModel the value returned from `model`,
889
- or its resolved value if it was a promise
890
- @param {Transition} transition
891
- @return {any | Promise<any>} if the value returned from this hook is
892
- a promise, the transition will pause until the transition
893
- resolves. Otherwise, non-promise return values are not
894
- utilized in any way.
895
- @since 1.0.0
896
- @public
897
- */
898
713
 
714
+ beforeModel(_transition) {}
899
715
 
900
- afterModel() {}
716
+ afterModel(_resolvedModel, _transition) {}
901
717
  /**
902
718
  A hook you can implement to optionally redirect to another route.
903
719
  Calling `this.transitionTo` from inside of the `redirect` hook will
@@ -920,7 +736,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
920
736
  */
921
737
 
922
738
 
923
- redirect() {}
739
+ redirect(_model, _transition) {}
924
740
  /**
925
741
  Called when the context is changed by router.js.
926
742
  @private
@@ -994,8 +810,9 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
994
810
 
995
811
 
996
812
  model(params, transition) {
997
- let name, sawParams, value;
998
- let queryParams = get(this, '_qp.map');
813
+ let name, sawParams, value; // SAFETY: Since `_qp` is protected we can't infer the type
814
+
815
+ let queryParams = get(this, '_qp').map;
999
816
 
1000
817
  for (let prop in params) {
1001
818
  if (prop === 'queryParams' || queryParams && prop in queryParams) {
@@ -1014,11 +831,14 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
1014
831
 
1015
832
  if (!name) {
1016
833
  if (sawParams) {
834
+ // SAFETY: This should be equivalent
1017
835
  return Object.assign({}, params);
1018
836
  } else {
1019
837
  if (transition.resolveIndex < 1) {
1020
838
  return;
1021
- }
839
+ } // SAFETY: These return types should be equivalent but router.js doesn't have enough
840
+ // generics to infer it.
841
+
1022
842
 
1023
843
  return transition[STATE_SYMBOL].routeInfos[transition.resolveIndex - 1].context;
1024
844
  }
@@ -1105,35 +925,14 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
1105
925
 
1106
926
 
1107
927
  setupController(controller, context, _transition) {
1108
- // eslint-disable-line no-unused-vars
1109
928
  if (controller && context !== undefined) {
1110
929
  set(controller, 'model', context);
1111
930
  }
1112
931
  }
1113
- /**
1114
- Returns the controller of the current route, or a parent (or any ancestor)
1115
- route in a route hierarchy.
1116
- The controller instance must already have been created, either through entering the
1117
- associated route or using `generateController`.
1118
- ```app/routes/post.js
1119
- import Route from '@ember/routing/route';
1120
- export default class PostRoute extends Route {
1121
- setupController(controller, post) {
1122
- super.setupController(controller, post);
1123
- this.controllerFor('posts').set('currentPost', post);
1124
- }
1125
- }
1126
- ```
1127
- @method controllerFor
1128
- @param {String} name the name of the route or controller
1129
- @return {Controller}
1130
- @since 1.0.0
1131
- @public
1132
- */
1133
932
 
1134
-
1135
- controllerFor(name, _skipAssert) {
933
+ controllerFor(name, _skipAssert = false) {
1136
934
  let owner = getOwner(this);
935
+ assert('Route is unexpectedly missing an owner', owner);
1137
936
  let route = owner.lookup(`route:${name}`);
1138
937
 
1139
938
  if (route && route.controllerName) {
@@ -1167,6 +966,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
1167
966
 
1168
967
  generateController(name) {
1169
968
  let owner = getOwner(this);
969
+ assert('Route is unexpectedly missing an owner', owner);
1170
970
  return generateController(owner, name);
1171
971
  }
1172
972
  /**
@@ -1208,6 +1008,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
1208
1008
  modelFor(_name) {
1209
1009
  let name;
1210
1010
  let owner = getOwner(this);
1011
+ assert('Route is unexpectedly missing an owner', owner);
1211
1012
  let transition = this._router && this._router._routerMicrolib ? this._router._routerMicrolib.activeTransition : undefined; // Only change the route name when there is an active transition.
1212
1013
  // Otherwise, use the passed in route name.
1213
1014
 
@@ -1228,7 +1029,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
1228
1029
  }
1229
1030
  }
1230
1031
 
1231
- return route && route.currentModel;
1032
+ return route === null || route === void 0 ? void 0 : route.currentModel;
1232
1033
  }
1233
1034
  /**
1234
1035
  `this[RENDER]` is used to render a template into a region of another template
@@ -1271,39 +1072,6 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
1271
1072
  once(this._router, '_setOutlets');
1272
1073
  }
1273
1074
  }
1274
- /**
1275
- Allows you to produce custom metadata for the route.
1276
- The return value of this method will be attached to
1277
- its corresponding RouteInfoWithAttributes object.
1278
- Example
1279
- ```app/routes/posts/index.js
1280
- import Route from '@ember/routing/route';
1281
- export default class PostsIndexRoute extends Route {
1282
- buildRouteInfoMetadata() {
1283
- return { title: 'Posts Page' }
1284
- }
1285
- }
1286
- ```
1287
- ```app/routes/application.js
1288
- import Route from '@ember/routing/route';
1289
- import { service } from '@ember/service';
1290
- export default class ApplicationRoute extends Route {
1291
- @service router
1292
- constructor() {
1293
- super(...arguments);
1294
- this.router.on('routeDidChange', transition => {
1295
- document.title = transition.to.metadata.title;
1296
- // would update document's title to "Posts Page"
1297
- });
1298
- }
1299
- }
1300
- ```
1301
- @method buildRouteInfoMetadata
1302
- @return any
1303
- @since 3.10.0
1304
- @public
1305
- */
1306
-
1307
1075
 
1308
1076
  buildRouteInfoMetadata() {}
1309
1077
 
@@ -1329,7 +1097,8 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
1329
1097
 
1330
1098
 
1331
1099
  get store() {
1332
- let owner = getOwner(this);
1100
+ const owner = getOwner(this);
1101
+ assert('Route is unexpectedly missing an owner', owner);
1333
1102
  let routeName = this.routeName;
1334
1103
  return {
1335
1104
  find(name, value) {
@@ -1361,6 +1130,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
1361
1130
  let combinedQueryParameterConfiguration;
1362
1131
  let controllerName = this.controllerName || this.routeName;
1363
1132
  let owner = getOwner(this);
1133
+ assert('Route is unexpectedly missing an owner', owner);
1364
1134
  let controller = owner.lookup(`controller:${controllerName}`);
1365
1135
  let queryParameterConfiguraton = get(this, 'queryParams');
1366
1136
  let hasRouterDefinedQueryParams = Object.keys(queryParameterConfiguraton).length > 0;
@@ -1370,7 +1140,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
1370
1140
  // this route find its query params and normalize their object shape them
1371
1141
  // merge in the query params for the route. As a mergedProperty,
1372
1142
  // Route#queryParams is always at least `{}`
1373
- let controllerDefinedQueryParameterConfiguration = get(controller, 'queryParams') || {};
1143
+ let controllerDefinedQueryParameterConfiguration = get(controller, 'queryParams') || [];
1374
1144
  let normalizedControllerQueryParameterConfiguration = normalizeControllerQueryParams(controllerDefinedQueryParameterConfiguration);
1375
1145
  combinedQueryParameterConfiguration = mergeEachQueryParams(normalizedControllerQueryParameterConfiguration, queryParameterConfiguraton);
1376
1146
  } else if (hasRouterDefinedQueryParams) {
@@ -1398,7 +1168,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
1398
1168
 
1399
1169
  let desc = combinedQueryParameterConfiguration[propName];
1400
1170
  let scope = desc.scope || 'model';
1401
- let parts;
1171
+ let parts = undefined;
1402
1172
 
1403
1173
  if (scope === 'controller') {
1404
1174
  parts = [];
@@ -1442,6 +1212,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
1442
1212
  */
1443
1213
  inactive: (prop, value) => {
1444
1214
  let qp = map[prop];
1215
+ assert('expected inactive callback to only be called for registered qps', qp);
1445
1216
 
1446
1217
  this._qpChanged(prop, value, qp);
1447
1218
  },
@@ -1453,6 +1224,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
1453
1224
  */
1454
1225
  active: (prop, value) => {
1455
1226
  let qp = map[prop];
1227
+ assert('expected active callback to only be called for registered qps', qp);
1456
1228
 
1457
1229
  this._qpChanged(prop, value, qp);
1458
1230
 
@@ -1465,6 +1237,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
1465
1237
  */
1466
1238
  allowOverrides: (prop, value) => {
1467
1239
  let qp = map[prop];
1240
+ assert('expected allowOverrides callback to only be called for registered qps', qp);
1468
1241
 
1469
1242
  this._qpChanged(prop, value, qp);
1470
1243
 
@@ -1495,7 +1268,9 @@ function routeInfoFor(route, routeInfos, offset = 0) {
1495
1268
  let current;
1496
1269
 
1497
1270
  for (let i = 0; i < routeInfos.length; i++) {
1498
- current = routeInfos[i].route;
1271
+ let routeInfo = routeInfos[i];
1272
+ assert('has current routeInfo', routeInfo);
1273
+ current = routeInfo.route;
1499
1274
 
1500
1275
  if (current === route) {
1501
1276
  return routeInfos[i + offset];
@@ -1522,6 +1297,7 @@ function buildRenderOptions(route, nameOrOptions, options) {
1522
1297
 
1523
1298
  assert('You passed undefined as the outlet name.', isDefaultRender || !(options && 'outlet' in options && options.outlet === undefined));
1524
1299
  let owner = getOwner(route);
1300
+ assert('Route is unexpectedly missing an owner', owner);
1525
1301
  let name, templateName, into, outlet, model;
1526
1302
  let controller = undefined;
1527
1303
 
@@ -1594,13 +1370,12 @@ function buildRenderOptions(route, nameOrOptions, options) {
1594
1370
  }
1595
1371
 
1596
1372
  export function getFullQueryParams(router, state) {
1597
- if (state['fullQueryParams']) {
1598
- return state['fullQueryParams'];
1373
+ if (state.fullQueryParams) {
1374
+ return state.fullQueryParams;
1599
1375
  }
1600
1376
 
1601
- let fullQueryParamsState = {};
1602
1377
  let haveAllRouteInfosResolved = state.routeInfos.every(routeInfo => routeInfo.route);
1603
- Object.assign(fullQueryParamsState, state.queryParams);
1378
+ let fullQueryParamsState = Object.assign({}, state.queryParams);
1604
1379
 
1605
1380
  router._deserializeQueryParams(state.routeInfos, fullQueryParamsState); // only cache query params state if all routeinfos have resolved; it's possible
1606
1381
  // for lazy routes to not have resolved when `getFullQueryParams` is called, so
@@ -1608,37 +1383,40 @@ export function getFullQueryParams(router, state) {
1608
1383
 
1609
1384
 
1610
1385
  if (haveAllRouteInfosResolved) {
1611
- state['fullQueryParams'] = fullQueryParamsState;
1386
+ state.fullQueryParams = fullQueryParamsState;
1612
1387
  }
1613
1388
 
1614
1389
  return fullQueryParamsState;
1615
1390
  }
1616
1391
 
1617
1392
  function getQueryParamsFor(route, state) {
1618
- state['queryParamsFor'] = state['queryParamsFor'] || {};
1393
+ state.queryParamsFor = state.queryParamsFor || {};
1619
1394
  let name = route.fullRouteName;
1395
+ let existing = state.queryParamsFor[name];
1620
1396
 
1621
- if (state['queryParamsFor'][name]) {
1622
- return state['queryParamsFor'][name];
1397
+ if (existing) {
1398
+ return existing;
1623
1399
  }
1624
1400
 
1625
1401
  let fullQueryParams = getFullQueryParams(route._router, state);
1626
- let params = state['queryParamsFor'][name] = {}; // Copy over all the query params for this route/controller into params hash.
1402
+ let params = state.queryParamsFor[name] = {}; // Copy over all the query params for this route/controller into params hash.
1403
+ // SAFETY: Since `_qp` is protected we can't infer the type
1627
1404
 
1628
- let qps = get(route, '_qp.qps');
1405
+ let qps = get(route, '_qp').qps;
1629
1406
 
1630
- for (let i = 0; i < qps.length; ++i) {
1407
+ for (let qp of qps) {
1631
1408
  // Put deserialized qp on params hash.
1632
- let qp = qps[i];
1633
1409
  let qpValueWasPassedIn = (qp.prop in fullQueryParams);
1634
1410
  params[qp.prop] = qpValueWasPassedIn ? fullQueryParams[qp.prop] : copyDefaultValue(qp.defaultValue);
1635
1411
  }
1636
1412
 
1637
1413
  return params;
1638
- }
1414
+ } // FIXME: This should probably actually return a `NativeArray` if the passed in value is an Array.
1415
+
1639
1416
 
1640
1417
  function copyDefaultValue(value) {
1641
1418
  if (Array.isArray(value)) {
1419
+ // SAFETY: We lost the type data about the array if we don't cast.
1642
1420
  return emberA(value.slice());
1643
1421
  }
1644
1422
 
@@ -1718,54 +1496,12 @@ function getEngineRouteName(engine, routeName) {
1718
1496
 
1719
1497
  return routeName;
1720
1498
  }
1721
- /**
1722
- A hook you can implement to convert the route's model into parameters
1723
- for the URL.
1724
-
1725
- ```app/router.js
1726
- // ...
1727
-
1728
- Router.map(function() {
1729
- this.route('post', { path: '/posts/:post_id' });
1730
- });
1731
-
1732
- ```
1733
-
1734
- ```app/routes/post.js
1735
- import Route from '@ember/routing/route';
1736
1499
 
1737
- export default class PostRoute extends Route {
1738
- model({ post_id }) {
1739
- // the server returns `{ id: 12 }`
1740
- return fetch(`/posts/${post_id}`;
1741
- }
1742
-
1743
- serialize(model) {
1744
- // this will make the URL `/posts/12`
1745
- return { post_id: model.id };
1746
- }
1747
- }
1748
- ```
1749
-
1750
- The default `serialize` method will insert the model's `id` into the
1751
- route's dynamic segment (in this case, `:post_id`) if the segment contains '_id'.
1752
- If the route has multiple dynamic segments or does not contain '_id', `serialize`
1753
- will return `getProperties(model, params)`
1754
-
1755
- This method is called when `transitionTo` is called with a context
1756
- in order to populate the URL.
1757
-
1758
- @method serialize
1759
- @param {Object} model the routes model
1760
- @param {Array} params an Array of parameter names for the current
1761
- route (in the example, `['post_id']`.
1762
- @return {Object} the serialized parameters
1763
- @since 1.0.0
1764
- @public
1765
- */
1766
-
1767
-
1768
- Route.prototype.serialize = defaultSerialize; // Set these here so they can be overridden with extend
1500
+ const defaultSerialize = Route.prototype.serialize;
1501
+ export { defaultSerialize };
1502
+ export function hasDefaultSerialize(route) {
1503
+ return route.serialize === defaultSerialize;
1504
+ } // Set these here so they can be overridden with extend
1769
1505
 
1770
1506
  Route.reopen({
1771
1507
  mergedProperties: ['queryParams'],
@@ -1824,15 +1560,22 @@ Route.reopen({
1824
1560
  @private
1825
1561
  */
1826
1562
  queryParamsDidChange(changed, _totalPresent, removed) {
1563
+ // SAFETY: Since `_qp` is protected we can't infer the type
1827
1564
  let qpMap = get(this, '_qp').map;
1828
1565
  let totalChanged = Object.keys(changed).concat(Object.keys(removed));
1829
1566
 
1830
- for (let i = 0; i < totalChanged.length; ++i) {
1831
- let qp = qpMap[totalChanged[i]];
1567
+ for (let change of totalChanged) {
1568
+ let qp = qpMap[change];
1569
+
1570
+ if (qp) {
1571
+ let options = this._optionsForQueryParam(qp);
1572
+
1573
+ assert('options exists', options && typeof options === 'object');
1832
1574
 
1833
- if (qp && get(this._optionsForQueryParam(qp), 'refreshModel') && this._router.currentState) {
1834
- this.refresh();
1835
- break;
1575
+ if (get(options, 'refreshModel') && this._router.currentState) {
1576
+ this.refresh();
1577
+ break;
1578
+ }
1836
1579
  }
1837
1580
  }
1838
1581
 
@@ -1859,15 +1602,15 @@ Route.reopen({
1859
1602
  let replaceUrl;
1860
1603
  stashParamNames(router, routeInfos);
1861
1604
 
1862
- for (let i = 0; i < qpMeta.qps.length; ++i) {
1863
- let qp = qpMeta.qps[i];
1605
+ for (let qp of qpMeta.qps) {
1864
1606
  let route = qp.route;
1865
1607
  let controller = route.controller;
1866
1608
  let presentKey = qp.urlKey in params && qp.urlKey; // Do a reverse lookup to see if the changed query
1867
1609
  // param URL key corresponds to a QP property on
1868
1610
  // this controller.
1869
1611
 
1870
- let value, svalue;
1612
+ let value;
1613
+ let svalue;
1871
1614
 
1872
1615
  if (changes.has(qp.urlKey)) {
1873
1616
  // Value updated in/before setupController
@@ -1885,9 +1628,10 @@ Route.reopen({
1885
1628
  svalue = qp.serializedDefaultValue;
1886
1629
  value = copyDefaultValue(qp.defaultValue);
1887
1630
  }
1888
- }
1631
+ } // SAFETY: Since `_qp` is protected we can't infer the type
1632
+
1889
1633
 
1890
- controller._qpDelegate = get(route, '_qp.states.inactive');
1634
+ controller._qpDelegate = get(route, '_qp').states.inactive;
1891
1635
  let thisQueryParamChanged = svalue !== qp.serializedValue;
1892
1636
 
1893
1637
  if (thisQueryParamChanged) {
@@ -1932,6 +1676,7 @@ Route.reopen({
1932
1676
  }
1933
1677
 
1934
1678
  qpMeta.qps.forEach(qp => {
1679
+ // SAFETY: Since `_qp` is protected we can't infer the type
1935
1680
  let routeQpMeta = get(qp.route, '_qp');
1936
1681
  let finalizedController = qp.route.controller;
1937
1682
  finalizedController['_qpDelegate'] = get(routeQpMeta, 'states.active');