ember-source 4.8.0-alpha.5 → 4.8.0-beta.2

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 (244) hide show
  1. package/CHANGELOG.md +11 -2
  2. package/blueprints/helper/files/__root__/{__collection__ → helpers}/__name__.ts +0 -0
  3. package/blueprints/helper/index.js +0 -15
  4. package/blueprints/helper-test/index.js +0 -3
  5. package/blueprints/helper-test/mocha-0.12-files/__root__/__testType__/{__collection__ → helpers}/__name__-test.js +0 -0
  6. package/blueprints/helper-test/mocha-files/__root__/__testType__/{__collection__ → helpers}/__name__-test.js +0 -0
  7. package/blueprints/helper-test/mocha-rfc-232-files/__root__/__testType__/{__collection__ → helpers}/__name__-test.ts +0 -0
  8. package/blueprints/helper-test/qunit-files/__root__/__testType__/{__collection__ → helpers}/__name__-test.js +0 -0
  9. package/blueprints/helper-test/qunit-rfc-232-files/__root__/__testType__/{__collection__ → helpers}/__name__-test.ts +0 -0
  10. package/blueprints-js/helper/files/__root__/{__collection__ → helpers}/__name__.js +0 -0
  11. package/blueprints-js/helper-test/mocha-0.12-files/__root__/__testType__/{__collection__ → helpers}/__name__-test.js +0 -0
  12. package/blueprints-js/helper-test/mocha-files/__root__/__testType__/{__collection__ → helpers}/__name__-test.js +0 -0
  13. package/blueprints-js/helper-test/mocha-rfc-232-files/__root__/__testType__/{__collection__ → helpers}/__name__-test.js +0 -0
  14. package/blueprints-js/helper-test/qunit-files/__root__/__testType__/{__collection__ → helpers}/__name__-test.js +0 -0
  15. package/blueprints-js/helper-test/qunit-rfc-232-files/__root__/__testType__/{__collection__ → helpers}/__name__-test.js +0 -0
  16. package/build-metadata.json +3 -3
  17. package/dist/dependencies/router_js.js +1 -1
  18. package/dist/ember-template-compiler.js +675 -18
  19. package/dist/ember-template-compiler.map +1 -1
  20. package/dist/ember-testing.js +11 -11
  21. package/dist/ember-testing.map +1 -1
  22. package/dist/ember.debug.js +19576 -20510
  23. package/dist/ember.debug.map +1 -1
  24. package/dist/header/license.js +1 -1
  25. package/dist/packages/@ember/-internals/glimmer/index.js +4 -2
  26. package/dist/packages/@ember/-internals/metal/index.js +214 -1094
  27. package/dist/packages/@ember/-internals/routing/index.js +1 -17
  28. package/dist/packages/@ember/-internals/runtime/index.js +3 -16
  29. package/dist/packages/@ember/-internals/runtime/lib/mixins/-proxy.js +2 -1
  30. package/dist/packages/@ember/-internals/runtime/lib/mixins/action_handler.js +4 -3
  31. package/dist/packages/@ember/-internals/runtime/lib/mixins/comparable.js +1 -1
  32. package/dist/packages/@ember/-internals/runtime/lib/mixins/container_proxy.js +1 -1
  33. package/dist/packages/@ember/-internals/runtime/lib/mixins/registry_proxy.js +1 -8
  34. package/dist/packages/@ember/-internals/runtime/lib/mixins/target_action_support.js +2 -1
  35. package/dist/packages/@ember/-internals/utils/index.js +3 -3
  36. package/dist/packages/@ember/-internals/views/lib/component_lookup.js +1 -1
  37. package/dist/packages/@ember/-internals/views/lib/mixins/action_support.js +2 -1
  38. package/dist/packages/@ember/-internals/views/lib/mixins/child_views_support.js +2 -1
  39. package/dist/packages/@ember/-internals/views/lib/mixins/class_names_support.js +2 -1
  40. package/dist/packages/@ember/-internals/views/lib/mixins/view_state_support.js +1 -1
  41. package/dist/packages/@ember/-internals/views/lib/mixins/view_support.js +2 -1
  42. package/dist/packages/@ember/-internals/views/lib/system/event_dispatcher.js +1 -1
  43. package/dist/packages/@ember/-internals/views/lib/views/core_view.js +3 -1
  44. package/dist/packages/@ember/application/index.js +876 -2
  45. package/dist/packages/@ember/application/instance.js +2 -2
  46. package/dist/packages/@ember/application/namespace.js +70 -1
  47. package/dist/packages/@ember/array/index.js +1503 -2
  48. package/dist/packages/@ember/array/mutable.js +1 -1
  49. package/dist/packages/@ember/array/proxy.js +307 -1
  50. package/dist/packages/@ember/canary-features/index.js +2 -2
  51. package/dist/packages/@ember/controller/index.js +260 -3
  52. package/dist/packages/@ember/debug/container-debug-adapter.js +99 -1
  53. package/dist/packages/@ember/debug/data-adapter.js +574 -1
  54. package/dist/packages/@ember/engine/index.js +5 -5
  55. package/dist/packages/@ember/engine/instance.js +4 -4
  56. package/dist/packages/@ember/enumerable/index.js +3 -1
  57. package/dist/packages/@ember/enumerable/mutable.js +4 -0
  58. package/dist/packages/@ember/{-internals/runtime/lib/system/object.js → object/-internals.js} +4 -17
  59. package/dist/packages/@ember/object/core.js +731 -1
  60. package/dist/packages/@ember/object/evented.js +93 -2
  61. package/dist/packages/@ember/object/index.js +76 -4
  62. package/dist/packages/@ember/object/internals.js +3 -2
  63. package/dist/packages/@ember/object/lib/computed/computed_macros.js +3 -1
  64. package/dist/packages/@ember/object/lib/computed/reduce_computed_macros.js +4 -3
  65. package/dist/packages/@ember/object/mixin.js +659 -1
  66. package/dist/packages/@ember/object/observable.js +341 -1
  67. package/dist/packages/@ember/object/promise-proxy-mixin.js +150 -1
  68. package/dist/packages/@ember/object/proxy.js +10 -1
  69. package/dist/packages/@ember/routing/-internals.js +7 -0
  70. package/dist/packages/@ember/routing/auto-location.js +249 -1
  71. package/dist/packages/@ember/routing/hash-location.js +169 -1
  72. package/dist/packages/@ember/routing/history-location.js +289 -1
  73. package/dist/packages/@ember/{-internals/routing/lib/system → routing/lib}/cache.js +0 -0
  74. package/dist/packages/@ember/{-internals/routing/lib/system → routing/lib}/controller_for.js +0 -0
  75. package/dist/packages/@ember/{-internals/routing/lib/system → routing/lib}/dsl.js +0 -0
  76. package/dist/packages/@ember/{-internals/routing/lib/system → routing/lib}/engines.js +0 -0
  77. package/dist/packages/@ember/{-internals/routing/lib/system → routing/lib}/generate_controller.js +0 -0
  78. package/dist/packages/@ember/{-internals/routing/lib/location/util.js → routing/lib/location-utils.js} +0 -0
  79. package/dist/packages/@ember/{-internals/routing/lib/system → routing/lib}/query_params.js +0 -0
  80. package/dist/packages/@ember/{-internals/routing/lib/system → routing/lib}/route-info.js +0 -0
  81. package/dist/packages/@ember/{-internals/routing/lib/system → routing/lib}/router_state.js +1 -1
  82. package/dist/packages/@ember/{-internals/routing/lib/services/routing.js → routing/lib/routing-service.js} +2 -2
  83. package/dist/packages/@ember/{-internals/routing/lib/system → routing/lib}/transition.js +0 -0
  84. package/dist/packages/@ember/{-internals/routing → routing}/lib/utils.js +0 -0
  85. package/dist/packages/@ember/routing/location.js +104 -1
  86. package/dist/packages/@ember/routing/none-location.js +123 -1
  87. package/dist/packages/@ember/routing/route.js +1700 -1
  88. package/dist/packages/@ember/routing/router-service.js +510 -1
  89. package/dist/packages/@ember/routing/router.js +1666 -1
  90. package/dist/packages/@ember/service/index.js +1 -1
  91. package/dist/packages/@ember/utils/index.js +7 -2
  92. package/dist/packages/@ember/{-internals/runtime → utils}/lib/compare.js +2 -2
  93. package/dist/packages/@ember/{-internals/runtime → utils}/lib/is-equal.js +0 -0
  94. package/dist/packages/@ember/utils/lib/is_blank.js +35 -0
  95. package/dist/packages/@ember/utils/lib/is_empty.js +68 -0
  96. package/dist/packages/@ember/utils/lib/is_none.js +27 -0
  97. package/dist/packages/@ember/utils/lib/is_present.js +38 -0
  98. package/dist/packages/@ember/{-internals/runtime → utils}/lib/type-of.js +2 -2
  99. package/dist/packages/ember/index.js +47 -28
  100. package/dist/packages/ember/version.js +1 -1
  101. package/dist/packages/ember-testing/lib/adapters/adapter.js +1 -1
  102. package/dist/packages/ember-testing/lib/helpers/current_path.js +2 -2
  103. package/dist/packages/ember-testing/lib/helpers/current_route_name.js +2 -2
  104. package/dist/packages/ember-testing/lib/helpers/current_url.js +1 -1
  105. package/docs/data.json +9428 -9189
  106. package/package.json +23 -8
  107. package/types/preview/@ember/-internals/resolver.d.ts +35 -0
  108. package/types/preview/@ember/application/-private/event-dispatcher.d.ts +18 -0
  109. package/types/preview/@ember/application/-private/registry.d.ts +15 -0
  110. package/types/preview/@ember/application/deprecations.d.ts +24 -0
  111. package/types/preview/@ember/application/index.d.ts +153 -0
  112. package/types/preview/@ember/application/instance.d.ts +9 -0
  113. package/types/preview/@ember/application/tsconfig.json +3 -0
  114. package/types/preview/@ember/application/types.d.ts +29 -0
  115. package/types/preview/@ember/array/-private/enumerable.d.ts +13 -0
  116. package/types/preview/@ember/array/-private/mutable-enumerable.d.ts +13 -0
  117. package/types/preview/@ember/array/-private/native-array.d.ts +23 -0
  118. package/types/preview/@ember/array/index.d.ts +243 -0
  119. package/types/preview/@ember/array/mutable.d.ts +94 -0
  120. package/types/preview/@ember/array/proxy.d.ts +29 -0
  121. package/types/preview/@ember/array/tsconfig.json +3 -0
  122. package/types/preview/@ember/component/-private/class-names-support.d.ts +27 -0
  123. package/types/preview/@ember/component/-private/core-view.d.ts +14 -0
  124. package/types/preview/@ember/component/-private/glimmer-interfaces.d.ts +45 -0
  125. package/types/preview/@ember/component/-private/signature-utils.d.ts +107 -0
  126. package/types/preview/@ember/component/-private/view-mixin.d.ts +59 -0
  127. package/types/preview/@ember/component/helper.d.ts +122 -0
  128. package/types/preview/@ember/component/index.d.ts +132 -0
  129. package/types/preview/@ember/component/template-only.d.ts +47 -0
  130. package/types/preview/@ember/component/tsconfig.json +3 -0
  131. package/types/preview/@ember/controller/index.d.ts +48 -0
  132. package/types/preview/@ember/controller/tsconfig.json +3 -0
  133. package/types/preview/@ember/debug/container-debug-adapter.d.ts +13 -0
  134. package/types/preview/@ember/debug/data-adapter.d.ts +64 -0
  135. package/types/preview/@ember/debug/index.d.ts +98 -0
  136. package/types/preview/@ember/debug/tsconfig.json +3 -0
  137. package/types/preview/@ember/destroyable/index.d.ts +23 -0
  138. package/types/preview/@ember/destroyable/tsconfig.json +3 -0
  139. package/types/preview/@ember/engine/-private/container-proxy-mixin.d.ts +17 -0
  140. package/types/preview/@ember/engine/-private/registry-proxy-mixin.d.ts +54 -0
  141. package/types/preview/@ember/engine/-private/types/initializer.d.ts +8 -0
  142. package/types/preview/@ember/engine/index.d.ts +45 -0
  143. package/types/preview/@ember/engine/instance.d.ts +24 -0
  144. package/types/preview/@ember/engine/tsconfig.json +3 -0
  145. package/types/preview/@ember/error/index.d.ts +6 -0
  146. package/types/preview/@ember/error/tsconfig.json +3 -0
  147. package/types/preview/@ember/helper/index.d.ts +49 -0
  148. package/types/preview/@ember/helper/tsconfig.json +3 -0
  149. package/types/preview/@ember/modifier/index.d.ts +33 -0
  150. package/types/preview/@ember/modifier/tsconfig.json +3 -0
  151. package/types/preview/@ember/object/-private/action-handler.d.ts +31 -0
  152. package/types/preview/@ember/object/-private/types.d.ts +63 -0
  153. package/types/preview/@ember/object/compat.d.ts +9 -0
  154. package/types/preview/@ember/object/computed.d.ts +263 -0
  155. package/types/preview/@ember/object/core.d.ts +89 -0
  156. package/types/preview/@ember/object/evented.d.ts +45 -0
  157. package/types/preview/@ember/object/events.d.ts +47 -0
  158. package/types/preview/@ember/object/index.d.ts +126 -0
  159. package/types/preview/@ember/object/internals.d.ts +17 -0
  160. package/types/preview/@ember/object/mixin.d.ts +19 -0
  161. package/types/preview/@ember/object/observable.d.ts +89 -0
  162. package/types/preview/@ember/object/observers.d.ts +34 -0
  163. package/types/preview/@ember/object/promise-proxy-mixin.d.ts +37 -0
  164. package/types/preview/@ember/object/proxy.d.ts +27 -0
  165. package/types/preview/@ember/object/tsconfig.json +3 -0
  166. package/types/preview/@ember/owner/index.d.ts +102 -0
  167. package/types/preview/@ember/owner/tsconfig.json +3 -0
  168. package/types/preview/@ember/polyfills/index.d.ts +23 -0
  169. package/types/preview/@ember/polyfills/tsconfig.json +3 -0
  170. package/types/preview/@ember/polyfills/types.d.ts +6 -0
  171. package/types/preview/@ember/routing/-private/router-dsl.d.ts +20 -0
  172. package/types/preview/@ember/routing/auto-location.d.ts +8 -0
  173. package/types/preview/@ember/routing/hash-location.d.ts +10 -0
  174. package/types/preview/@ember/routing/history-location.d.ts +9 -0
  175. package/types/preview/@ember/routing/index.d.ts +20 -0
  176. package/types/preview/@ember/routing/none-location.d.ts +11 -0
  177. package/types/preview/@ember/routing/route-info.d.ts +74 -0
  178. package/types/preview/@ember/routing/route.d.ts +533 -0
  179. package/types/preview/@ember/routing/router-service.d.ts +351 -0
  180. package/types/preview/@ember/routing/router.d.ts +49 -0
  181. package/types/preview/@ember/routing/transition.d.ts +126 -0
  182. package/types/preview/@ember/routing/tsconfig.json +3 -0
  183. package/types/preview/@ember/routing/types.d.ts +15 -0
  184. package/types/preview/@ember/runloop/-private/backburner.d.ts +43 -0
  185. package/types/preview/@ember/runloop/-private/types.d.ts +9 -0
  186. package/types/preview/@ember/runloop/index.d.ts +175 -0
  187. package/types/preview/@ember/runloop/tsconfig.json +3 -0
  188. package/types/preview/@ember/runloop/types.d.ts +5 -0
  189. package/types/preview/@ember/service/index.d.ts +25 -0
  190. package/types/preview/@ember/service/tsconfig.json +3 -0
  191. package/types/preview/@ember/string/index.d.ts +9 -0
  192. package/types/preview/@ember/string/tsconfig.json +3 -0
  193. package/types/preview/@ember/template/-private/handlebars.d.ts +7 -0
  194. package/types/preview/@ember/template/index.d.ts +5 -0
  195. package/types/preview/@ember/template/tsconfig.json +3 -0
  196. package/types/preview/@ember/test/adapter.d.ts +22 -0
  197. package/types/preview/@ember/test/index.d.ts +49 -0
  198. package/types/preview/@ember/test/tsconfig.json +3 -0
  199. package/types/preview/@ember/utils/-private/types.d.ts +39 -0
  200. package/types/preview/@ember/utils/index.d.ts +42 -0
  201. package/types/preview/@ember/utils/tsconfig.json +3 -0
  202. package/types/preview/ember/-private/type-utils.d.ts +54 -0
  203. package/types/preview/ember/index.d.ts +381 -0
  204. package/types/preview/ember/tsconfig.json +3 -0
  205. package/types/preview/index.d.ts +120 -0
  206. package/types/preview/tsconfig.json +6 -0
  207. package/blueprints/helper/mu-files/__root__/__collection__/__name__.js +0 -7
  208. package/blueprints-js/helper/mu-files/__root__/__collection__/__name__.js +0 -7
  209. package/dist/packages/@ember/-internals/extension-support/index.js +0 -2
  210. package/dist/packages/@ember/-internals/extension-support/lib/container_debug_adapter.js +0 -96
  211. package/dist/packages/@ember/-internals/extension-support/lib/data_adapter.js +0 -576
  212. package/dist/packages/@ember/-internals/routing/lib/ext/controller.js +0 -224
  213. package/dist/packages/@ember/-internals/routing/lib/location/api.js +0 -104
  214. package/dist/packages/@ember/-internals/routing/lib/location/auto_location.js +0 -250
  215. package/dist/packages/@ember/-internals/routing/lib/location/hash_location.js +0 -170
  216. package/dist/packages/@ember/-internals/routing/lib/location/history_location.js +0 -290
  217. package/dist/packages/@ember/-internals/routing/lib/location/none_location.js +0 -124
  218. package/dist/packages/@ember/-internals/routing/lib/services/router.js +0 -506
  219. package/dist/packages/@ember/-internals/routing/lib/system/route.js +0 -1696
  220. package/dist/packages/@ember/-internals/routing/lib/system/router.js +0 -1662
  221. package/dist/packages/@ember/-internals/runtime/lib/mixins/array.js +0 -1501
  222. package/dist/packages/@ember/-internals/runtime/lib/mixins/enumerable.js +0 -3
  223. package/dist/packages/@ember/-internals/runtime/lib/mixins/evented.js +0 -91
  224. package/dist/packages/@ember/-internals/runtime/lib/mixins/mutable_enumerable.js +0 -4
  225. package/dist/packages/@ember/-internals/runtime/lib/mixins/observable.js +0 -339
  226. package/dist/packages/@ember/-internals/runtime/lib/mixins/promise_proxy.js +0 -149
  227. package/dist/packages/@ember/-internals/runtime/lib/system/array_proxy.js +0 -305
  228. package/dist/packages/@ember/-internals/runtime/lib/system/core_object.js +0 -730
  229. package/dist/packages/@ember/-internals/runtime/lib/system/namespace.js +0 -69
  230. package/dist/packages/@ember/-internals/runtime/lib/system/object_proxy.js +0 -7
  231. package/dist/packages/@ember/application/lib/application.js +0 -870
  232. package/dist/packages/@ember/controller/lib/controller_mixin.js +0 -42
  233. package/dist/packages/@ember/runloop/type-tests.ts/begin-end.test.js +0 -5
  234. package/dist/packages/@ember/runloop/type-tests.ts/bind.test.js +0 -59
  235. package/dist/packages/@ember/runloop/type-tests.ts/cancel.test.js +0 -5
  236. package/dist/packages/@ember/runloop/type-tests.ts/debounce.test.js +0 -77
  237. package/dist/packages/@ember/runloop/type-tests.ts/join.test.js +0 -38
  238. package/dist/packages/@ember/runloop/type-tests.ts/later.test.js +0 -38
  239. package/dist/packages/@ember/runloop/type-tests.ts/next.test.js +0 -38
  240. package/dist/packages/@ember/runloop/type-tests.ts/once.test.js +0 -38
  241. package/dist/packages/@ember/runloop/type-tests.ts/run.test.js +0 -38
  242. package/dist/packages/@ember/runloop/type-tests.ts/schedule-once.test.js +0 -39
  243. package/dist/packages/@ember/runloop/type-tests.ts/schedule.test.js +0 -39
  244. package/dist/packages/@ember/runloop/type-tests.ts/throttle.test.js +0 -77
@@ -1 +1,1700 @@
1
- export { Route as default } from '@ember/-internals/routing';
1
+ var __decorate = this && this.__decorate || function (decorators, target, key, desc) {
2
+ var c = arguments.length,
3
+ r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,
4
+ d;
5
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+
9
+ import { privatize as P } from '@ember/-internals/container';
10
+ import { addObserver, defineProperty, descriptorForProperty, flushAsyncObservers } from '@ember/-internals/metal';
11
+ import { getOwner } from '@ember/-internals/owner';
12
+ import { BucketCache } from '@ember/routing/-internals';
13
+ import EmberObject, { computed, get, set, getProperties, setProperties } from '@ember/object';
14
+ import Evented from '@ember/object/evented';
15
+ import { A as emberA } from '@ember/array';
16
+ import { ActionHandler } from '@ember/-internals/runtime';
17
+ import { isEmpty, typeOf } from '@ember/utils';
18
+ import { isProxy, lookupDescriptor } from '@ember/-internals/utils';
19
+ import Controller from '@ember/controller';
20
+ import { assert, info, isTesting } from '@ember/debug';
21
+ import EngineInstance from '@ember/engine/instance';
22
+ import { dependentKeyCompat } from '@ember/object/compat';
23
+ import { once } from '@ember/runloop';
24
+ import { DEBUG } from '@glimmer/env';
25
+ import { PARAMS_SYMBOL, STATE_SYMBOL } from 'router_js';
26
+ import EmberRouter from '@ember/routing/router';
27
+ import { generateController } from '@ember/routing/-internals';
28
+ import { calculateCacheKey, deprecateTransitionMethods, normalizeControllerQueryParams, prefixRouteNameArg, stashParamNames } from './lib/utils';
29
+ export const ROUTE_CONNECTIONS = new WeakMap();
30
+ const RENDER = Symbol('render');
31
+
32
+ class Route extends EmberObject.extend(ActionHandler, Evented) {
33
+ constructor(owner) {
34
+ super(owner);
35
+ this.context = {};
36
+
37
+ if (owner) {
38
+ let router = owner.lookup('router:main');
39
+ let bucketCache = owner.lookup(P`-bucket-cache:main`);
40
+ assert('ROUTER BUG: Expected route injections to be defined on the route. This is an internal bug, please open an issue on Github if you see this message!', router instanceof EmberRouter && bucketCache instanceof BucketCache);
41
+ this._router = router;
42
+ this._bucketCache = bucketCache;
43
+ this._topLevelViewTemplate = owner.lookup('template:-outlet');
44
+ this._environment = owner.lookup('-environment:main');
45
+ }
46
+ }
47
+ /**
48
+ A hook you can implement to convert the route's model into parameters
49
+ for the URL.
50
+ ```app/router.js
51
+ // ...
52
+ Router.map(function() {
53
+ this.route('post', { path: '/posts/:post_id' });
54
+ });
55
+ ```
56
+ ```app/routes/post.js
57
+ import Route from '@ember/routing/route';
58
+ export default class PostRoute extends Route {
59
+ model({ post_id }) {
60
+ // the server returns `{ id: 12 }`
61
+ return fetch(`/posts/${post_id}`;
62
+ }
63
+ serialize(model) {
64
+ // this will make the URL `/posts/12`
65
+ return { post_id: model.id };
66
+ }
67
+ }
68
+ ```
69
+ The default `serialize` method will insert the model's `id` into the
70
+ route's dynamic segment (in this case, `:post_id`) if the segment contains '_id'.
71
+ If the route has multiple dynamic segments or does not contain '_id', `serialize`
72
+ will return `getProperties(model, params)`
73
+ This method is called when `transitionTo` is called with a context
74
+ in order to populate the URL.
75
+ @method serialize
76
+ @param {Object} model the routes model
77
+ @param {Array} params an Array of parameter names for the current
78
+ route (in the example, `['post_id']`.
79
+ @return {Object} the serialized parameters
80
+ @since 1.0.0
81
+ @public
82
+ */
83
+
84
+
85
+ serialize(model, params) {
86
+ if (params.length < 1 || !model) {
87
+ return;
88
+ }
89
+
90
+ let object = {};
91
+
92
+ if (params.length === 1) {
93
+ let [name] = params;
94
+ assert('has name', name);
95
+
96
+ if (name in model) {
97
+ object[name] = get(model, name);
98
+ } else if (/_id$/.test(name)) {
99
+ object[name] = get(model, 'id');
100
+ } else if (isProxy(model)) {
101
+ object[name] = get(model, name);
102
+ }
103
+ } else {
104
+ object = getProperties(model, params);
105
+ }
106
+
107
+ return object;
108
+ }
109
+ /**
110
+ Sets the name for this route, including a fully resolved name for routes
111
+ inside engines.
112
+ @private
113
+ @method _setRouteName
114
+ @param {String} name
115
+ */
116
+
117
+
118
+ _setRouteName(name) {
119
+ this.routeName = name;
120
+ let owner = getOwner(this);
121
+ assert('Expected route to have EngineInstance as owner', owner instanceof EngineInstance);
122
+ this.fullRouteName = getEngineRouteName(owner, name);
123
+ }
124
+ /**
125
+ @private
126
+ @method _stashNames
127
+ */
128
+
129
+
130
+ _stashNames(routeInfo, dynamicParent) {
131
+ if (this._names) {
132
+ return;
133
+ }
134
+
135
+ let names = this._names = routeInfo['_names'];
136
+
137
+ if (!names.length) {
138
+ routeInfo = dynamicParent;
139
+ names = routeInfo && routeInfo['_names'] || [];
140
+ } // SAFETY: Since `_qp` is protected we can't infer the type
141
+
142
+
143
+ let qps = get(this, '_qp').qps;
144
+ let namePaths = new Array(names.length);
145
+
146
+ for (let a = 0; a < names.length; ++a) {
147
+ namePaths[a] = `${routeInfo.name}.${names[a]}`;
148
+ }
149
+
150
+ for (let qp of qps) {
151
+ if (qp.scope === 'model') {
152
+ qp.parts = namePaths;
153
+ }
154
+ }
155
+ }
156
+ /**
157
+ @private
158
+ @property _activeQPChanged
159
+ */
160
+
161
+
162
+ _activeQPChanged(qp, value) {
163
+ this._router._activeQPChanged(qp.scopedPropertyName, value);
164
+ }
165
+ /**
166
+ @private
167
+ @method _updatingQPChanged
168
+ */
169
+
170
+
171
+ _updatingQPChanged(qp) {
172
+ this._router._updatingQPChanged(qp.urlKey);
173
+ }
174
+ /**
175
+ Returns a hash containing the parameters of an ancestor route.
176
+ You may notice that `this.paramsFor` sometimes works when referring to a
177
+ child route, but this behavior should not be relied upon as only ancestor
178
+ routes are certain to be loaded in time.
179
+ Example
180
+ ```app/router.js
181
+ // ...
182
+ Router.map(function() {
183
+ this.route('member', { path: ':name' }, function() {
184
+ this.route('interest', { path: ':interest' });
185
+ });
186
+ });
187
+ ```
188
+ ```app/routes/member.js
189
+ import Route from '@ember/routing/route';
190
+ export default class MemberRoute extends Route {
191
+ queryParams = {
192
+ memberQp: { refreshModel: true }
193
+ }
194
+ }
195
+ ```
196
+ ```app/routes/member/interest.js
197
+ import Route from '@ember/routing/route';
198
+ export default class MemberInterestRoute extends Route {
199
+ queryParams = {
200
+ interestQp: { refreshModel: true }
201
+ }
202
+ model() {
203
+ return this.paramsFor('member');
204
+ }
205
+ }
206
+ ```
207
+ If we visit `/turing/maths?memberQp=member&interestQp=interest` the model for
208
+ the `member.interest` route is a hash with:
209
+ * `name`: `turing`
210
+ * `memberQp`: `member`
211
+ @method paramsFor
212
+ @param {String} name
213
+ @return {Object} hash containing the parameters of the route `name`
214
+ @since 1.4.0
215
+ @public
216
+ */
217
+
218
+
219
+ paramsFor(name) {
220
+ let owner = getOwner(this);
221
+ assert('Route is unexpectedly missing an owner', owner);
222
+ let route = owner.lookup(`route:${name}`);
223
+
224
+ if (route === undefined) {
225
+ return {};
226
+ }
227
+
228
+ let transition = this._router._routerMicrolib.activeTransition;
229
+ let state = transition ? transition[STATE_SYMBOL] : this._router._routerMicrolib.state;
230
+ let fullName = route.fullRouteName;
231
+ let params = Object.assign({}, state.params[fullName]);
232
+ let queryParams = getQueryParamsFor(route, state);
233
+ return Object.entries(queryParams).reduce((params, [key, value]) => {
234
+ assert(`The route '${this.routeName}' has both a dynamic segment and query param with name '${key}'. Please rename one to avoid collisions.`, !params[key]);
235
+ params[key] = value;
236
+ return params;
237
+ }, params);
238
+ }
239
+ /**
240
+ Serializes the query parameter key
241
+ @method serializeQueryParamKey
242
+ @param {String} controllerPropertyName
243
+ @private
244
+ */
245
+
246
+
247
+ serializeQueryParamKey(controllerPropertyName) {
248
+ return controllerPropertyName;
249
+ }
250
+ /**
251
+ Serializes value of the query parameter based on defaultValueType
252
+ @method serializeQueryParam
253
+ @param {Object} value
254
+ @param {String} urlKey
255
+ @param {String} defaultValueType
256
+ @private
257
+ */
258
+
259
+
260
+ serializeQueryParam(value, _urlKey, defaultValueType) {
261
+ // urlKey isn't used here, but anyone overriding
262
+ // can use it to provide serialization specific
263
+ // to a certain query param.
264
+ return this._router._serializeQueryParam(value, defaultValueType);
265
+ }
266
+ /**
267
+ Deserializes value of the query parameter based on defaultValueType
268
+ @method deserializeQueryParam
269
+ @param {Object} value
270
+ @param {String} urlKey
271
+ @param {String} defaultValueType
272
+ @private
273
+ */
274
+
275
+
276
+ deserializeQueryParam(value, _urlKey, defaultValueType) {
277
+ // urlKey isn't used here, but anyone overriding
278
+ // can use it to provide deserialization specific
279
+ // to a certain query param.
280
+ return this._router._deserializeQueryParam(value, defaultValueType);
281
+ }
282
+ /**
283
+ @private
284
+ @property _optionsForQueryParam
285
+ */
286
+
287
+
288
+ _optionsForQueryParam(qp) {
289
+ const queryParams = get(this, 'queryParams');
290
+ return get(queryParams, qp.urlKey) || get(queryParams, qp.prop) || queryParams[qp.urlKey] || queryParams[qp.prop] || {};
291
+ }
292
+ /**
293
+ A hook you can use to reset controller values either when the model
294
+ changes or the route is exiting.
295
+ ```app/routes/articles.js
296
+ import Route from '@ember/routing/route';
297
+ export default class ArticlesRoute extends Route {
298
+ resetController(controller, isExiting, transition) {
299
+ if (isExiting && transition.targetName !== 'error') {
300
+ controller.set('page', 1);
301
+ }
302
+ }
303
+ }
304
+ ```
305
+ @method resetController
306
+ @param {Controller} controller instance
307
+ @param {Boolean} isExiting
308
+ @param {Object} transition
309
+ @since 1.7.0
310
+ @public
311
+ */
312
+
313
+
314
+ resetController(_controller, _isExiting, _transition) {
315
+ return this;
316
+ }
317
+ /**
318
+ @private
319
+ @method exit
320
+ */
321
+
322
+
323
+ exit(transition) {
324
+ this.deactivate(transition);
325
+ this.trigger('deactivate', transition);
326
+ this.teardownViews();
327
+ }
328
+ /**
329
+ @private
330
+ @method _internalReset
331
+ @since 3.6.0
332
+ */
333
+
334
+
335
+ _internalReset(isExiting, transition) {
336
+ let controller = this.controller; // SAFETY: Since `_qp` is protected we can't infer the type
337
+
338
+ controller['_qpDelegate'] = get(this, '_qp').states.inactive;
339
+ this.resetController(controller, isExiting, transition);
340
+ }
341
+ /**
342
+ @private
343
+ @method enter
344
+ */
345
+
346
+
347
+ enter(transition) {
348
+ ROUTE_CONNECTIONS.set(this, []);
349
+ this.activate(transition);
350
+ this.trigger('activate', transition);
351
+ }
352
+ /**
353
+ This event is triggered when the router enters the route. It is
354
+ not executed when the model for the route changes.
355
+ ```app/routes/application.js
356
+ import { on } from '@ember/object/evented';
357
+ import Route from '@ember/routing/route';
358
+ export default Route.extend({
359
+ collectAnalytics: on('activate', function(){
360
+ collectAnalytics();
361
+ })
362
+ });
363
+ ```
364
+ @event activate
365
+ @since 1.9.0
366
+ @public
367
+ */
368
+
369
+ /**
370
+ This event is triggered when the router completely exits this
371
+ route. It is not executed when the model for the route changes.
372
+ ```app/routes/index.js
373
+ import { on } from '@ember/object/evented';
374
+ import Route from '@ember/routing/route';
375
+ export default Route.extend({
376
+ trackPageLeaveAnalytics: on('deactivate', function(){
377
+ trackPageLeaveAnalytics();
378
+ })
379
+ });
380
+ ```
381
+ @event deactivate
382
+ @since 1.9.0
383
+ @public
384
+ */
385
+
386
+ /**
387
+ This hook is executed when the router completely exits this route. It is
388
+ not executed when the model for the route changes.
389
+ @method deactivate
390
+ @param {Transition} transition
391
+ @since 1.0.0
392
+ @public
393
+ */
394
+
395
+
396
+ deactivate(_transition) {}
397
+ /**
398
+ This hook is executed when the router enters the route. It is not executed
399
+ when the model for the route changes.
400
+ @method activate
401
+ @param {Transition} transition
402
+ @since 1.0.0
403
+ @public
404
+ */
405
+
406
+
407
+ activate(_transition) {}
408
+ /**
409
+ Transition the application into another route. The route may
410
+ be either a single route or route path:
411
+ ```javascript
412
+ this.transitionTo('blogPosts');
413
+ this.transitionTo('blogPosts.recentEntries');
414
+ ```
415
+ Optionally supply a model for the route in question. The model
416
+ will be serialized into the URL using the `serialize` hook of
417
+ the route:
418
+ ```javascript
419
+ this.transitionTo('blogPost', aPost);
420
+ ```
421
+ If a literal is passed (such as a number or a string), it will
422
+ be treated as an identifier instead. In this case, the `model`
423
+ hook of the route will be triggered:
424
+ ```javascript
425
+ this.transitionTo('blogPost', 1);
426
+ ```
427
+ Multiple models will be applied last to first recursively up the
428
+ route tree.
429
+ ```app/routes.js
430
+ // ...
431
+ Router.map(function() {
432
+ this.route('blogPost', { path:':blogPostId' }, function() {
433
+ this.route('blogComment', { path: ':blogCommentId' });
434
+ });
435
+ });
436
+ export default Router;
437
+ ```
438
+ ```javascript
439
+ this.transitionTo('blogComment', aPost, aComment);
440
+ this.transitionTo('blogComment', 1, 13);
441
+ ```
442
+ It is also possible to pass a URL (a string that starts with a
443
+ `/`).
444
+ ```javascript
445
+ this.transitionTo('/');
446
+ this.transitionTo('/blog/post/1/comment/13');
447
+ this.transitionTo('/blog/posts?sort=title');
448
+ ```
449
+ An options hash with a `queryParams` property may be provided as
450
+ the final argument to add query parameters to the destination URL.
451
+ ```javascript
452
+ this.transitionTo('blogPost', 1, {
453
+ queryParams: { showComments: 'true' }
454
+ });
455
+ // if you just want to transition the query parameters without changing the route
456
+ this.transitionTo({ queryParams: { sort: 'date' } });
457
+ ```
458
+ See also [replaceWith](#method_replaceWith).
459
+ Simple Transition Example
460
+ ```app/routes.js
461
+ // ...
462
+ Router.map(function() {
463
+ this.route('index');
464
+ this.route('secret');
465
+ this.route('fourOhFour', { path: '*:' });
466
+ });
467
+ export default Router;
468
+ ```
469
+ ```app/routes/index.js
470
+ import Route from '@ember/routing/route';
471
+ import { action } from '@ember/object';
472
+ export default class IndexRoute extends Route {
473
+ @action
474
+ moveToSecret(context) {
475
+ if (authorized()) {
476
+ this.transitionTo('secret', context);
477
+ } else {
478
+ this.transitionTo('fourOhFour');
479
+ }
480
+ }
481
+ }
482
+ ```
483
+ Transition to a nested route
484
+ ```app/router.js
485
+ // ...
486
+ Router.map(function() {
487
+ this.route('articles', { path: '/articles' }, function() {
488
+ this.route('new');
489
+ });
490
+ });
491
+ export default Router;
492
+ ```
493
+ ```app/routes/index.js
494
+ import Route from '@ember/routing/route';
495
+ import { action } from '@ember/object';
496
+ export default class IndexRoute extends Route {
497
+ @action
498
+ transitionToNewArticle() {
499
+ this.transitionTo('articles.new');
500
+ }
501
+ }
502
+ ```
503
+ Multiple Models Example
504
+ ```app/router.js
505
+ // ...
506
+ Router.map(function() {
507
+ this.route('index');
508
+ this.route('breakfast', { path: ':breakfastId' }, function() {
509
+ this.route('cereal', { path: ':cerealId' });
510
+ });
511
+ });
512
+ export default Router;
513
+ ```
514
+ ```app/routes/index.js
515
+ import Route from '@ember/routing/route';
516
+ import { action } from '@ember/object';
517
+ export default class IndexRoute extends Route {
518
+ @action
519
+ moveToChocolateCereal() {
520
+ let cereal = { cerealId: 'ChocolateYumminess' };
521
+ let breakfast = { breakfastId: 'CerealAndMilk' };
522
+ this.transitionTo('breakfast.cereal', breakfast, cereal);
523
+ }
524
+ }
525
+ ```
526
+ Nested Route with Query String Example
527
+ ```app/routes.js
528
+ // ...
529
+ Router.map(function() {
530
+ this.route('fruits', function() {
531
+ this.route('apples');
532
+ });
533
+ });
534
+ export default Router;
535
+ ```
536
+ ```app/routes/index.js
537
+ import Route from '@ember/routing/route';
538
+ export default class IndexRoute extends Route {
539
+ @action
540
+ transitionToApples() {
541
+ this.transitionTo('fruits.apples', { queryParams: { color: 'red' } });
542
+ }
543
+ }
544
+ ```
545
+ @method transitionTo
546
+ @param {String} [name] the name of the route or a URL.
547
+ @param {...Object} [models] the model(s) or identifier(s) to be used while
548
+ transitioning to the route.
549
+ @param {Object} [options] optional hash with a queryParams property
550
+ containing a mapping of query parameters. May be supplied as the only
551
+ parameter to trigger a query-parameter-only transition.
552
+ @return {Transition} the transition object associated with this
553
+ attempted transition
554
+ @since 1.0.0
555
+ @deprecated Use transitionTo from the Router service instead.
556
+ @public
557
+ */
558
+
559
+
560
+ transitionTo(...args) {
561
+ deprecateTransitionMethods('route', 'transitionTo');
562
+ return this._router.transitionTo(...prefixRouteNameArg(this, args));
563
+ }
564
+ /**
565
+ Perform a synchronous transition into another route without attempting
566
+ to resolve promises, update the URL, or abort any currently active
567
+ asynchronous transitions (i.e. regular transitions caused by
568
+ `transitionTo` or URL changes).
569
+ This method is handy for performing intermediate transitions on the
570
+ way to a final destination route, and is called internally by the
571
+ default implementations of the `error` and `loading` handlers.
572
+ @method intermediateTransitionTo
573
+ @param {String} name the name of the route
574
+ @param {...Object} models the model(s) to be used while transitioning
575
+ to the route.
576
+ @since 1.2.0
577
+ @public
578
+ */
579
+
580
+
581
+ intermediateTransitionTo(...args) {
582
+ let [name, ...preparedArgs] = prefixRouteNameArg(this, args);
583
+
584
+ this._router.intermediateTransitionTo(name, ...preparedArgs);
585
+ }
586
+ /**
587
+ Refresh the model on this route and any child routes, firing the
588
+ `beforeModel`, `model`, and `afterModel` hooks in a similar fashion
589
+ to how routes are entered when transitioning in from other route.
590
+ The current route params (e.g. `article_id`) will be passed in
591
+ to the respective model hooks, and if a different model is returned,
592
+ `setupController` and associated route hooks will re-fire as well.
593
+ An example usage of this method is re-querying the server for the
594
+ latest information using the same parameters as when the route
595
+ was first entered.
596
+ Note that this will cause `model` hooks to fire even on routes
597
+ that were provided a model object when the route was initially
598
+ entered.
599
+ @method refresh
600
+ @return {Transition} the transition object associated with this
601
+ attempted transition
602
+ @since 1.4.0
603
+ @public
604
+ */
605
+
606
+
607
+ refresh() {
608
+ return this._router._routerMicrolib.refresh(this);
609
+ }
610
+ /**
611
+ Transition into another route while replacing the current URL, if possible.
612
+ This will replace the current history entry instead of adding a new one.
613
+ Beside that, it is identical to `transitionTo` in all other respects. See
614
+ 'transitionTo' for additional information regarding multiple models.
615
+ Example
616
+ ```app/router.js
617
+ // ...
618
+ Router.map(function() {
619
+ this.route('index');
620
+ this.route('secret');
621
+ });
622
+ export default Router;
623
+ ```
624
+ ```app/routes/secret.js
625
+ import Route from '@ember/routing/route';
626
+ export default class SecretRoute Route {
627
+ afterModel() {
628
+ if (!authorized()){
629
+ this.replaceWith('index');
630
+ }
631
+ }
632
+ }
633
+ ```
634
+ @method replaceWith
635
+ @param {String} name the name of the route or a URL
636
+ @param {...Object} models the model(s) or identifier(s) to be used while
637
+ transitioning to the route.
638
+ @param {Object} [options] optional hash with a queryParams property
639
+ containing a mapping of query parameters
640
+ @return {Transition} the transition object associated with this
641
+ attempted transition
642
+ @since 1.0.0
643
+ @deprecated Use replaceWith from the Router service instead.
644
+ @public
645
+ */
646
+
647
+
648
+ replaceWith(...args) {
649
+ deprecateTransitionMethods('route', 'replaceWith');
650
+ return this._router.replaceWith(...prefixRouteNameArg(this, args));
651
+ }
652
+ /**
653
+ This hook is the entry point for router.js
654
+ @private
655
+ @method setup
656
+ */
657
+
658
+
659
+ setup(context, transition) {
660
+ let controllerName = this.controllerName || this.routeName;
661
+ let definedController = this.controllerFor(controllerName, true);
662
+ let controller = definedController !== null && definedController !== void 0 ? definedController : this.generateController(controllerName); // SAFETY: Since `_qp` is protected we can't infer the type
663
+
664
+ let queryParams = get(this, '_qp'); // Assign the route's controller so that it can more easily be
665
+ // referenced in action handlers. Side effects. Side effects everywhere.
666
+
667
+ if (!this.controller) {
668
+ let propNames = queryParams.propertyNames;
669
+ addQueryParamsObservers(controller, propNames);
670
+ this.controller = controller;
671
+ }
672
+
673
+ let states = queryParams.states;
674
+ controller._qpDelegate = states.allowOverrides;
675
+
676
+ if (transition) {
677
+ // Update the model dep values used to calculate cache keys.
678
+ stashParamNames(this._router, transition[STATE_SYMBOL].routeInfos);
679
+ let cache = this._bucketCache;
680
+ let params = transition[PARAMS_SYMBOL];
681
+ let allParams = queryParams.propertyNames;
682
+ allParams.forEach(prop => {
683
+ let aQp = queryParams.map[prop];
684
+ assert('expected aQp', aQp);
685
+ aQp.values = params;
686
+ let cacheKey = calculateCacheKey(aQp.route.fullRouteName, aQp.parts, aQp.values);
687
+ let value = cache.lookup(cacheKey, prop, aQp.undecoratedDefaultValue);
688
+ set(controller, prop, value);
689
+ });
690
+ let qpValues = getQueryParamsFor(this, transition[STATE_SYMBOL]);
691
+ setProperties(controller, qpValues);
692
+ }
693
+
694
+ this.setupController(controller, context, transition);
695
+
696
+ if (this._environment.options.shouldRender) {
697
+ this[RENDER]();
698
+ } // Setup can cause changes to QPs which need to be propogated immediately in
699
+ // some situations. Eventually, we should work on making these async somehow.
700
+
701
+
702
+ flushAsyncObservers(false);
703
+ }
704
+ /*
705
+ Called when a query parameter for this route changes, regardless of whether the route
706
+ is currently part of the active route hierarchy. This will update the query parameter's
707
+ value in the cache so if this route becomes active, the cache value has been updated.
708
+ */
709
+
710
+
711
+ _qpChanged(prop, value, qp) {
712
+ if (!qp) {
713
+ return;
714
+ } // Update model-dep cache
715
+
716
+
717
+ let cache = this._bucketCache;
718
+ let cacheKey = calculateCacheKey(qp.route.fullRouteName, qp.parts, qp.values);
719
+ cache.stash(cacheKey, prop, value);
720
+ }
721
+
722
+ beforeModel(_transition) {}
723
+
724
+ afterModel(_resolvedModel, _transition) {}
725
+ /**
726
+ A hook you can implement to optionally redirect to another route.
727
+ Calling `this.transitionTo` from inside of the `redirect` hook will
728
+ abort the current transition (into the route that has implemented `redirect`).
729
+ `redirect` and `afterModel` behave very similarly and are
730
+ called almost at the same time, but they have an important
731
+ distinction when calling `this.transitionTo` to a child route
732
+ of the current route. From `afterModel`, this new transition
733
+ invalidates the current transition, causing `beforeModel`,
734
+ `model`, and `afterModel` hooks to be called again. But the
735
+ same transition started from `redirect` does _not_ invalidate
736
+ the current transition. In other words, by the time the `redirect`
737
+ hook has been called, both the resolved model and the attempted
738
+ entry into this route are considered fully validated.
739
+ @method redirect
740
+ @param {Object} model the model for this route
741
+ @param {Transition} transition the transition object associated with the current transition
742
+ @since 1.0.0
743
+ @public
744
+ */
745
+
746
+
747
+ redirect(_model, _transition) {}
748
+ /**
749
+ Called when the context is changed by router.js.
750
+ @private
751
+ @method contextDidChange
752
+ */
753
+
754
+
755
+ contextDidChange() {
756
+ this.currentModel = this.context;
757
+ }
758
+ /**
759
+ A hook you can implement to convert the URL into the model for
760
+ this route.
761
+ ```app/router.js
762
+ // ...
763
+ Router.map(function() {
764
+ this.route('post', { path: '/posts/:post_id' });
765
+ });
766
+ export default Router;
767
+ ```
768
+ The model for the `post` route is `store.findRecord('post', params.post_id)`.
769
+ By default, if your route has a dynamic segment ending in `_id`:
770
+ * The model class is determined from the segment (`post_id`'s
771
+ class is `App.Post`)
772
+ * The find method is called on the model class with the value of
773
+ the dynamic segment.
774
+ Note that for routes with dynamic segments, this hook is not always
775
+ executed. If the route is entered through a transition (e.g. when
776
+ using the `link-to` Handlebars helper or the `transitionTo` method
777
+ of routes), and a model context is already provided this hook
778
+ is not called.
779
+ A model context does not include a primitive string or number,
780
+ which does cause the model hook to be called.
781
+ Routes without dynamic segments will always execute the model hook.
782
+ ```javascript
783
+ // no dynamic segment, model hook always called
784
+ this.transitionTo('posts');
785
+ // model passed in, so model hook not called
786
+ thePost = store.findRecord('post', 1);
787
+ this.transitionTo('post', thePost);
788
+ // integer passed in, model hook is called
789
+ this.transitionTo('post', 1);
790
+ // model id passed in, model hook is called
791
+ // useful for forcing the hook to execute
792
+ thePost = store.findRecord('post', 1);
793
+ this.transitionTo('post', thePost.id);
794
+ ```
795
+ This hook follows the asynchronous/promise semantics
796
+ described in the documentation for `beforeModel`. In particular,
797
+ if a promise returned from `model` fails, the error will be
798
+ handled by the `error` hook on `Route`.
799
+ Example
800
+ ```app/routes/post.js
801
+ import Route from '@ember/routing/route';
802
+ export default class PostRoute extends Route {
803
+ model(params) {
804
+ return this.store.findRecord('post', params.post_id);
805
+ }
806
+ }
807
+ ```
808
+ @method model
809
+ @param {Object} params the parameters extracted from the URL
810
+ @param {Transition} transition
811
+ @return {any | Promise<any>} the model for this route. If
812
+ a promise is returned, the transition will pause until
813
+ the promise resolves, and the resolved value of the promise
814
+ will be used as the model for this route.
815
+ @since 1.0.0
816
+ @public
817
+ */
818
+
819
+
820
+ model(params, transition) {
821
+ let name, sawParams, value; // SAFETY: Since `_qp` is protected we can't infer the type
822
+
823
+ let queryParams = get(this, '_qp').map;
824
+
825
+ for (let prop in params) {
826
+ if (prop === 'queryParams' || queryParams && prop in queryParams) {
827
+ continue;
828
+ }
829
+
830
+ let match = prop.match(/^(.*)_id$/);
831
+
832
+ if (match !== null) {
833
+ name = match[1];
834
+ value = params[prop];
835
+ }
836
+
837
+ sawParams = true;
838
+ }
839
+
840
+ if (!name) {
841
+ if (sawParams) {
842
+ // SAFETY: This should be equivalent
843
+ return Object.assign({}, params);
844
+ } else {
845
+ if (transition.resolveIndex < 1) {
846
+ return;
847
+ } // SAFETY: This should be correct, but TS is unable to infer this.
848
+
849
+
850
+ return transition[STATE_SYMBOL].routeInfos[transition.resolveIndex - 1].context;
851
+ }
852
+ }
853
+
854
+ return this.findModel(name, value);
855
+ }
856
+ /**
857
+ @private
858
+ @method deserialize
859
+ @param {Object} params the parameters extracted from the URL
860
+ @param {Transition} transition
861
+ @return {any | Promise<any>} the model for this route.
862
+ Router.js hook.
863
+ */
864
+
865
+
866
+ deserialize(_params, transition) {
867
+ return this.model(this._paramsFor(this.routeName, _params), transition);
868
+ }
869
+ /**
870
+ @method findModel
871
+ @param {String} type the model type
872
+ @param {Object} value the value passed to find
873
+ @private
874
+ */
875
+
876
+
877
+ findModel(...args) {
878
+ return get(this, 'store').find(...args);
879
+ }
880
+ /**
881
+ A hook you can use to setup the controller for the current route.
882
+ This method is called with the controller for the current route and the
883
+ model supplied by the `model` hook.
884
+ By default, the `setupController` hook sets the `model` property of
885
+ the controller to the specified `model` when it is not `undefined`.
886
+ If you implement the `setupController` hook in your Route, it will
887
+ prevent this default behavior. If you want to preserve that behavior
888
+ when implementing your `setupController` function, make sure to call
889
+ `super`:
890
+ ```app/routes/photos.js
891
+ import Route from '@ember/routing/route';
892
+ export default class PhotosRoute extends Route {
893
+ model() {
894
+ return this.store.findAll('photo');
895
+ }
896
+ setupController(controller, model) {
897
+ super.setupController(controller, model);
898
+ this.controllerFor('application').set('showingPhotos', true);
899
+ }
900
+ }
901
+ ```
902
+ The provided controller will be one resolved based on the name
903
+ of this route.
904
+ If no explicit controller is defined, Ember will automatically create one.
905
+ As an example, consider the router:
906
+ ```app/router.js
907
+ // ...
908
+ Router.map(function() {
909
+ this.route('post', { path: '/posts/:post_id' });
910
+ });
911
+ export default Router;
912
+ ```
913
+ If you have defined a file for the post controller,
914
+ the framework will use it.
915
+ If it is not defined, a basic `Controller` instance would be used.
916
+ @example Behavior of a basic Controller
917
+ ```app/routes/post.js
918
+ import Route from '@ember/routing/route';
919
+ export default class PostRoute extends Route {
920
+ setupController(controller, model) {
921
+ controller.set('model', model);
922
+ }
923
+ });
924
+ ```
925
+ @method setupController
926
+ @param {Controller} controller instance
927
+ @param {Object} model
928
+ @param {Transition} [transition]
929
+ @since 1.0.0
930
+ @public
931
+ */
932
+
933
+
934
+ setupController(controller, context, _transition) {
935
+ if (controller && context !== undefined) {
936
+ set(controller, 'model', context);
937
+ }
938
+ }
939
+
940
+ controllerFor(name, _skipAssert = false) {
941
+ let owner = getOwner(this);
942
+ assert('Route is unexpectedly missing an owner', owner);
943
+ let route = owner.lookup(`route:${name}`);
944
+
945
+ if (route && route.controllerName) {
946
+ name = route.controllerName;
947
+ }
948
+
949
+ let controller = owner.lookup(`controller:${name}`); // NOTE: We're specifically checking that skipAssert is true, because according
950
+ // to the old API the second parameter was model. We do not want people who
951
+ // passed a model to skip the assertion.
952
+
953
+ assert(`The controller named '${name}' could not be found. Make sure that this route exists and has already been entered at least once. If you are accessing a controller not associated with a route, make sure the controller class is explicitly defined.`, controller !== undefined || _skipAssert === true);
954
+ assert(`Expected controller:${name} to be an instance of Controller`, controller === undefined || controller instanceof Controller);
955
+ return controller;
956
+ }
957
+ /**
958
+ Generates a controller for a route.
959
+ Example
960
+ ```app/routes/post.js
961
+ import Route from '@ember/routing/route';
962
+ export default class Post extends Route {
963
+ setupController(controller, post) {
964
+ super.setupController(controller, post);
965
+ this.generateController('posts');
966
+ }
967
+ }
968
+ ```
969
+ @method generateController
970
+ @param {String} name the name of the controller
971
+ @private
972
+ */
973
+
974
+
975
+ generateController(name) {
976
+ let owner = getOwner(this);
977
+ assert('Route is unexpectedly missing an owner', owner);
978
+ return generateController(owner, name);
979
+ }
980
+ /**
981
+ Returns the resolved model of a parent (or any ancestor) route
982
+ in a route hierarchy. During a transition, all routes
983
+ must resolve a model object, and if a route
984
+ needs access to a parent route's model in order to
985
+ resolve a model (or just reuse the model from a parent),
986
+ it can call `this.modelFor(theNameOfParentRoute)` to
987
+ retrieve it. If the ancestor route's model was a promise,
988
+ its resolved result is returned.
989
+ Example
990
+ ```app/router.js
991
+ // ...
992
+ Router.map(function() {
993
+ this.route('post', { path: '/posts/:post_id' }, function() {
994
+ this.route('comments');
995
+ });
996
+ });
997
+ export default Router;
998
+ ```
999
+ ```app/routes/post/comments.js
1000
+ import Route from '@ember/routing/route';
1001
+ export default class PostCommentsRoute extends Route {
1002
+ model() {
1003
+ let post = this.modelFor('post');
1004
+ return post.comments;
1005
+ }
1006
+ }
1007
+ ```
1008
+ @method modelFor
1009
+ @param {String} name the name of the route
1010
+ @return {Object} the model object
1011
+ @since 1.0.0
1012
+ @public
1013
+ */
1014
+
1015
+
1016
+ modelFor(_name) {
1017
+ let name;
1018
+ let owner = getOwner(this);
1019
+ assert('Expected router owner to be an EngineInstance', owner instanceof EngineInstance);
1020
+ let transition = this._router && this._router._routerMicrolib ? this._router._routerMicrolib.activeTransition : undefined; // Only change the route name when there is an active transition.
1021
+ // Otherwise, use the passed in route name.
1022
+
1023
+ if (owner.routable && transition !== undefined) {
1024
+ name = getEngineRouteName(owner, _name);
1025
+ } else {
1026
+ name = _name;
1027
+ }
1028
+
1029
+ let route = owner.lookup(`route:${name}`); // If we are mid-transition, we want to try and look up
1030
+ // resolved parent contexts on the current transitionEvent.
1031
+
1032
+ if (transition !== undefined && transition !== null) {
1033
+ let modelLookupName = route && route.routeName || name;
1034
+
1035
+ if (Object.prototype.hasOwnProperty.call(transition.resolvedModels, modelLookupName)) {
1036
+ return transition.resolvedModels[modelLookupName];
1037
+ }
1038
+ }
1039
+
1040
+ return route === null || route === void 0 ? void 0 : route.currentModel;
1041
+ }
1042
+ /**
1043
+ `this[RENDER]` is used to render a template into a region of another template
1044
+ (indicated by an `{{outlet}}`).
1045
+ @method this[RENDER]
1046
+ @param {String} name the name of the template to render
1047
+ @param {Object} [options] the options
1048
+ @param {String} [options.into] the template to render into,
1049
+ referenced by name. Defaults to the parent template
1050
+ @param {String} [options.outlet] the outlet inside `options.into` to render into.
1051
+ Defaults to 'main'
1052
+ @param {String|Object} [options.controller] the controller to use for this template,
1053
+ referenced by name or as a controller instance. Defaults to the Route's paired controller
1054
+ @param {Object} [options.model] the model object to set on `options.controller`.
1055
+ Defaults to the return value of the Route's model hook
1056
+ @private
1057
+ */
1058
+
1059
+
1060
+ [RENDER](name, options) {
1061
+ let renderOptions = buildRenderOptions(this, name, options);
1062
+ ROUTE_CONNECTIONS.get(this).push(renderOptions);
1063
+ once(this._router, '_setOutlets');
1064
+ }
1065
+
1066
+ willDestroy() {
1067
+ this.teardownViews();
1068
+ }
1069
+ /**
1070
+ @private
1071
+ @method teardownViews
1072
+ */
1073
+
1074
+
1075
+ teardownViews() {
1076
+ let connections = ROUTE_CONNECTIONS.get(this);
1077
+
1078
+ if (connections !== undefined && connections.length > 0) {
1079
+ ROUTE_CONNECTIONS.set(this, []);
1080
+ once(this._router, '_setOutlets');
1081
+ }
1082
+ }
1083
+
1084
+ buildRouteInfoMetadata() {}
1085
+
1086
+ _paramsFor(routeName, params) {
1087
+ let transition = this._router._routerMicrolib.activeTransition;
1088
+
1089
+ if (transition !== undefined) {
1090
+ return this.paramsFor(routeName);
1091
+ }
1092
+
1093
+ return params;
1094
+ }
1095
+ /**
1096
+ Store property provides a hook for data persistence libraries to inject themselves.
1097
+ By default, this store property provides the exact same functionality previously
1098
+ in the model hook.
1099
+ Currently, the required interface is:
1100
+ `store.find(modelName, findArguments)`
1101
+ @property store
1102
+ @type {Object}
1103
+ @private
1104
+ */
1105
+
1106
+
1107
+ get store() {
1108
+ const owner = getOwner(this);
1109
+ assert('Route is unexpectedly missing an owner', owner);
1110
+ let routeName = this.routeName;
1111
+ return {
1112
+ find(name, value) {
1113
+ let modelClass = owner.factoryFor(`model:${name}`);
1114
+ assert(`You used the dynamic segment \`${name}_id\` in your route ` + `\`${routeName}\` for which Ember requires you provide a ` + `data-loading implementation. Commonly, that is done by ` + `adding a model hook implementation on the route ` + `(\`model({${name}_id}) {\`) or by injecting an implemention of ` + `a data store: \`@service store;\`.`, Boolean(modelClass));
1115
+
1116
+ if (!modelClass) {
1117
+ return;
1118
+ }
1119
+
1120
+ modelClass = modelClass.class;
1121
+ assert(`You used the dynamic segment \`${name}_id\` in your route ` + `\`${routeName}\` for which Ember requires you provide a ` + `data-loading implementation. Commonly, that is done by ` + `adding a model hook implementation on the route ` + `(\`model({${name}_id}) {\`) or by injecting an implemention of ` + `a data store: \`@service store;\`.\n\n` + `Rarely, applications may attempt to use a legacy behavior where ` + `the model class (in this case \`${name}\`) is resolved and the ` + `\`find\` method on that class is invoked to load data. In this ` + `application, a model of \`${name}\` was found but it did not ` + `provide a \`find\` method. You should not add a \`find\` ` + `method to your model. Instead, please implement an appropriate ` + `\`model\` hook on the \`${routeName}\` route.`, typeof modelClass.find === 'function');
1122
+ return modelClass.find(value);
1123
+ }
1124
+
1125
+ };
1126
+ }
1127
+
1128
+ set store(value) {
1129
+ defineProperty(this, 'store', null, value);
1130
+ }
1131
+ /**
1132
+ @private
1133
+ @property _qp
1134
+ */
1135
+
1136
+
1137
+ get _qp() {
1138
+ let combinedQueryParameterConfiguration = {};
1139
+ let controllerName = this.controllerName || this.routeName;
1140
+ let owner = getOwner(this);
1141
+ assert('Route is unexpectedly missing an owner', owner);
1142
+ let controller = owner.lookup(`controller:${controllerName}`);
1143
+ let queryParameterConfiguraton = get(this, 'queryParams');
1144
+ let hasRouterDefinedQueryParams = Object.keys(queryParameterConfiguraton).length > 0;
1145
+
1146
+ if (controller) {
1147
+ assert('Expected an instance of controller', controller instanceof Controller); // the developer has authored a controller class in their application for
1148
+ // this route find its query params and normalize their object shape them
1149
+ // merge in the query params for the route. As a mergedProperty,
1150
+ // Route#queryParams is always at least `{}`
1151
+
1152
+ let controllerDefinedQueryParameterConfiguration = get(controller, 'queryParams') || [];
1153
+ let normalizedControllerQueryParameterConfiguration = normalizeControllerQueryParams(controllerDefinedQueryParameterConfiguration);
1154
+ combinedQueryParameterConfiguration = mergeEachQueryParams(normalizedControllerQueryParameterConfiguration, queryParameterConfiguraton);
1155
+ } else if (hasRouterDefinedQueryParams) {
1156
+ // the developer has not defined a controller but *has* supplied route query params.
1157
+ // Generate a class for them so we can later insert default values
1158
+ controller = generateController(owner, controllerName);
1159
+ combinedQueryParameterConfiguration = queryParameterConfiguraton;
1160
+ }
1161
+
1162
+ let qps = [];
1163
+ let map = {};
1164
+ let propertyNames = [];
1165
+
1166
+ for (let propName in combinedQueryParameterConfiguration) {
1167
+ if (!Object.prototype.hasOwnProperty.call(combinedQueryParameterConfiguration, propName)) {
1168
+ continue;
1169
+ } // to support the dubious feature of using unknownProperty
1170
+ // on queryParams configuration
1171
+
1172
+
1173
+ if (propName === 'unknownProperty' || propName === '_super') {
1174
+ // possible todo: issue deprecation warning?
1175
+ continue;
1176
+ }
1177
+
1178
+ let desc = combinedQueryParameterConfiguration[propName];
1179
+ assert(`[BUG] missing query parameter configuration for ${propName}`, desc);
1180
+ let scope = desc.scope || 'model';
1181
+ let parts = undefined;
1182
+
1183
+ if (scope === 'controller') {
1184
+ parts = [];
1185
+ }
1186
+
1187
+ let urlKey = desc.as || this.serializeQueryParamKey(propName);
1188
+ let defaultValue = get(controller, propName);
1189
+ defaultValue = copyDefaultValue(defaultValue);
1190
+ let type = desc.type || typeOf(defaultValue);
1191
+ let defaultValueSerialized = this.serializeQueryParam(defaultValue, urlKey, type);
1192
+ let scopedPropertyName = `${controllerName}:${propName}`;
1193
+ let qp = {
1194
+ undecoratedDefaultValue: get(controller, propName),
1195
+ defaultValue,
1196
+ serializedDefaultValue: defaultValueSerialized,
1197
+ serializedValue: defaultValueSerialized,
1198
+ type,
1199
+ urlKey,
1200
+ prop: propName,
1201
+ scopedPropertyName,
1202
+ controllerName,
1203
+ route: this,
1204
+ parts,
1205
+ values: null,
1206
+ scope
1207
+ };
1208
+ map[propName] = map[urlKey] = map[scopedPropertyName] = qp;
1209
+ qps.push(qp);
1210
+ propertyNames.push(propName);
1211
+ }
1212
+
1213
+ return {
1214
+ qps,
1215
+ map,
1216
+ propertyNames,
1217
+ states: {
1218
+ /*
1219
+ Called when a query parameter changes in the URL, this route cares
1220
+ about that query parameter, but the route is not currently
1221
+ in the active route hierarchy.
1222
+ */
1223
+ inactive: (prop, value) => {
1224
+ let qp = map[prop];
1225
+ assert('expected inactive callback to only be called for registered qps', qp);
1226
+
1227
+ this._qpChanged(prop, value, qp);
1228
+ },
1229
+
1230
+ /*
1231
+ Called when a query parameter changes in the URL, this route cares
1232
+ about that query parameter, and the route is currently
1233
+ in the active route hierarchy.
1234
+ */
1235
+ active: (prop, value) => {
1236
+ let qp = map[prop];
1237
+ assert('expected active callback to only be called for registered qps', qp);
1238
+
1239
+ this._qpChanged(prop, value, qp);
1240
+
1241
+ return this._activeQPChanged(qp, value);
1242
+ },
1243
+
1244
+ /*
1245
+ Called when a value of a query parameter this route handles changes in a controller
1246
+ and the route is currently in the active route hierarchy.
1247
+ */
1248
+ allowOverrides: (prop, value) => {
1249
+ let qp = map[prop];
1250
+ assert('expected allowOverrides callback to only be called for registered qps', qp);
1251
+
1252
+ this._qpChanged(prop, value, qp);
1253
+
1254
+ return this._updatingQPChanged(qp);
1255
+ }
1256
+ }
1257
+ };
1258
+ }
1259
+
1260
+ }
1261
+
1262
+ Route.isRouteFactory = true;
1263
+
1264
+ __decorate([computed], Route.prototype, "store", null);
1265
+
1266
+ __decorate([computed], Route.prototype, "_qp", null);
1267
+
1268
+ function parentRoute(route) {
1269
+ let routeInfo = routeInfoFor(route, route._router._routerMicrolib.state.routeInfos, -1);
1270
+ return routeInfo && routeInfo.route;
1271
+ }
1272
+
1273
+ function routeInfoFor(route, routeInfos, offset = 0) {
1274
+ if (!routeInfos) {
1275
+ return;
1276
+ }
1277
+
1278
+ let current;
1279
+
1280
+ for (let i = 0; i < routeInfos.length; i++) {
1281
+ let routeInfo = routeInfos[i];
1282
+ assert('has current routeInfo', routeInfo);
1283
+ current = routeInfo.route;
1284
+
1285
+ if (current === route) {
1286
+ return routeInfos[i + offset];
1287
+ }
1288
+ }
1289
+
1290
+ return;
1291
+ }
1292
+
1293
+ function buildRenderOptions(route, nameOrOptions, options) {
1294
+ let isDefaultRender = !nameOrOptions && !options;
1295
+
1296
+ let _name;
1297
+
1298
+ if (!isDefaultRender) {
1299
+ if (typeof nameOrOptions === 'object' && !options) {
1300
+ _name = route.templateName || route.routeName;
1301
+ options = nameOrOptions;
1302
+ } else {
1303
+ assert('The name in the given arguments is undefined or empty string', !isEmpty(nameOrOptions));
1304
+ _name = nameOrOptions;
1305
+ }
1306
+ }
1307
+
1308
+ assert('You passed undefined as the outlet name.', isDefaultRender || !(options && 'outlet' in options && options.outlet === undefined));
1309
+ let owner = getOwner(route);
1310
+ assert('Route is unexpectedly missing an owner', owner);
1311
+ let name, templateName, into, outlet, model;
1312
+ let controller;
1313
+
1314
+ if (options) {
1315
+ into = options.into && options.into.replace(/\//g, '.');
1316
+ outlet = options.outlet;
1317
+ controller = options.controller;
1318
+ model = options.model;
1319
+ }
1320
+
1321
+ outlet = outlet || 'main';
1322
+
1323
+ if (isDefaultRender) {
1324
+ name = route.routeName;
1325
+ templateName = route.templateName || name;
1326
+ } else {
1327
+ name = _name.replace(/\//g, '.');
1328
+ templateName = name;
1329
+ }
1330
+
1331
+ if (controller === undefined) {
1332
+ if (isDefaultRender) {
1333
+ controller = route.controllerName || owner.lookup(`controller:${name}`);
1334
+ } else {
1335
+ controller = owner.lookup(`controller:${name}`) || route.controllerName || route.routeName;
1336
+ }
1337
+ }
1338
+
1339
+ if (typeof controller === 'string') {
1340
+ let controllerName = controller;
1341
+ controller = owner.lookup(`controller:${controllerName}`);
1342
+ assert(`You passed \`controller: '${controllerName}'\` into the \`render\` method, but no such controller could be found.`, isDefaultRender || controller !== undefined);
1343
+ }
1344
+
1345
+ assert('Expected an instance of controller', controller instanceof Controller);
1346
+
1347
+ if (model === undefined) {
1348
+ model = route.currentModel;
1349
+ } else {
1350
+ controller.set('model', model);
1351
+ }
1352
+
1353
+ let template = owner.lookup(`template:${templateName}`);
1354
+ assert(`Could not find "${templateName}" template, view, or component.`, isDefaultRender || template !== undefined);
1355
+ let parent;
1356
+
1357
+ if (into && (parent = parentRoute(route)) && into === parent.routeName) {
1358
+ into = undefined;
1359
+ }
1360
+
1361
+ let renderOptions = {
1362
+ owner,
1363
+ into,
1364
+ outlet,
1365
+ name,
1366
+ controller,
1367
+ model,
1368
+ template: template !== undefined ? template(owner) : route._topLevelViewTemplate(owner)
1369
+ };
1370
+
1371
+ if (DEBUG) {
1372
+ let LOG_VIEW_LOOKUPS = get(route._router, 'namespace.LOG_VIEW_LOOKUPS');
1373
+
1374
+ if (LOG_VIEW_LOOKUPS && !template) {
1375
+ info(`Could not find "${name}" template. Nothing will be rendered`, {
1376
+ fullName: `template:${name}`
1377
+ });
1378
+ }
1379
+ }
1380
+
1381
+ return renderOptions;
1382
+ }
1383
+
1384
+ export function getFullQueryParams(router, state) {
1385
+ if (state.fullQueryParams) {
1386
+ return state.fullQueryParams;
1387
+ }
1388
+
1389
+ let haveAllRouteInfosResolved = state.routeInfos.every(routeInfo => routeInfo.route);
1390
+ let fullQueryParamsState = Object.assign({}, state.queryParams);
1391
+
1392
+ router._deserializeQueryParams(state.routeInfos, fullQueryParamsState); // only cache query params state if all routeinfos have resolved; it's possible
1393
+ // for lazy routes to not have resolved when `getFullQueryParams` is called, so
1394
+ // we wait until all routes have resolved prior to caching query params state
1395
+
1396
+
1397
+ if (haveAllRouteInfosResolved) {
1398
+ state.fullQueryParams = fullQueryParamsState;
1399
+ }
1400
+
1401
+ return fullQueryParamsState;
1402
+ }
1403
+
1404
+ function getQueryParamsFor(route, state) {
1405
+ state.queryParamsFor = state.queryParamsFor || {};
1406
+ let name = route.fullRouteName;
1407
+ let existing = state.queryParamsFor[name];
1408
+
1409
+ if (existing) {
1410
+ return existing;
1411
+ }
1412
+
1413
+ let fullQueryParams = getFullQueryParams(route._router, state);
1414
+ let params = state.queryParamsFor[name] = {}; // Copy over all the query params for this route/controller into params hash.
1415
+ // SAFETY: Since `_qp` is protected we can't infer the type
1416
+
1417
+ let qps = get(route, '_qp').qps;
1418
+
1419
+ for (let qp of qps) {
1420
+ // Put deserialized qp on params hash.
1421
+ let qpValueWasPassedIn = (qp.prop in fullQueryParams);
1422
+ params[qp.prop] = qpValueWasPassedIn ? fullQueryParams[qp.prop] : copyDefaultValue(qp.defaultValue);
1423
+ }
1424
+
1425
+ return params;
1426
+ } // FIXME: This should probably actually return a `NativeArray` if the passed in value is an Array.
1427
+
1428
+
1429
+ function copyDefaultValue(value) {
1430
+ if (Array.isArray(value)) {
1431
+ // SAFETY: We lost the type data about the array if we don't cast.
1432
+ return emberA(value.slice());
1433
+ }
1434
+
1435
+ return value;
1436
+ }
1437
+ /*
1438
+ Merges all query parameters from a controller with those from
1439
+ a route, returning a new object and avoiding any mutations to
1440
+ the existing objects.
1441
+ */
1442
+
1443
+
1444
+ function mergeEachQueryParams(controllerQP, routeQP) {
1445
+ let qps = {};
1446
+ let keysAlreadyMergedOrSkippable = {
1447
+ defaultValue: true,
1448
+ type: true,
1449
+ scope: true,
1450
+ as: true
1451
+ }; // first loop over all controller qps, merging them with any matching route qps
1452
+ // into a new empty object to avoid mutating.
1453
+
1454
+ for (let cqpName in controllerQP) {
1455
+ if (!Object.prototype.hasOwnProperty.call(controllerQP, cqpName)) {
1456
+ continue;
1457
+ }
1458
+
1459
+ qps[cqpName] = Object.assign(Object.assign({}, controllerQP[cqpName]), routeQP[cqpName]); // allows us to skip this QP when we check route QPs.
1460
+
1461
+ keysAlreadyMergedOrSkippable[cqpName] = true;
1462
+ } // loop over all route qps, skipping those that were merged in the first pass
1463
+ // because they also appear in controller qps
1464
+
1465
+
1466
+ for (let rqpName in routeQP) {
1467
+ if (!Object.prototype.hasOwnProperty.call(routeQP, rqpName) || keysAlreadyMergedOrSkippable[rqpName]) {
1468
+ continue;
1469
+ }
1470
+
1471
+ qps[rqpName] = Object.assign(Object.assign({}, routeQP[rqpName]), controllerQP[rqpName]);
1472
+ }
1473
+
1474
+ return qps;
1475
+ }
1476
+
1477
+ function addQueryParamsObservers(controller, propNames) {
1478
+ propNames.forEach(prop => {
1479
+ if (descriptorForProperty(controller, prop) === undefined) {
1480
+ let desc = lookupDescriptor(controller, prop);
1481
+
1482
+ if (desc !== null && (typeof desc.get === 'function' || typeof desc.set === 'function')) {
1483
+ defineProperty(controller, prop, dependentKeyCompat({
1484
+ get: desc.get,
1485
+ set: desc.set
1486
+ }));
1487
+ }
1488
+ }
1489
+
1490
+ addObserver(controller, `${prop}.[]`, controller, controller._qpChanged, false);
1491
+ });
1492
+ }
1493
+
1494
+ function getEngineRouteName(engine, routeName) {
1495
+ if (engine.routable) {
1496
+ let prefix = engine.mountPoint;
1497
+
1498
+ if (routeName === 'application') {
1499
+ return prefix;
1500
+ } else {
1501
+ return `${prefix}.${routeName}`;
1502
+ }
1503
+ }
1504
+
1505
+ return routeName;
1506
+ }
1507
+
1508
+ const defaultSerialize = Route.prototype.serialize;
1509
+ export { defaultSerialize };
1510
+ export function hasDefaultSerialize(route) {
1511
+ return route.serialize === defaultSerialize;
1512
+ } // Set these here so they can be overridden with extend
1513
+
1514
+ Route.reopen({
1515
+ mergedProperties: ['queryParams'],
1516
+ queryParams: {},
1517
+ templateName: null,
1518
+ controllerName: null,
1519
+
1520
+ send(...args) {
1521
+ assert(`Attempted to call .send() with the action '${args[0]}' on the destroyed route '${this.routeName}'.`, !this.isDestroying && !this.isDestroyed);
1522
+
1523
+ if (this._router && this._router._routerMicrolib || !isTesting()) {
1524
+ this._router.send(...args);
1525
+ } else {
1526
+ let name = args.shift();
1527
+ let action = this.actions[name];
1528
+
1529
+ if (action) {
1530
+ return action.apply(this, args);
1531
+ }
1532
+ }
1533
+ },
1534
+
1535
+ /**
1536
+ The controller associated with this route.
1537
+ Example
1538
+ ```app/routes/form.js
1539
+ import Route from '@ember/routing/route';
1540
+ import { action } from '@ember/object';
1541
+ export default class FormRoute extends Route {
1542
+ @action
1543
+ willTransition(transition) {
1544
+ if (this.controller.get('userHasEnteredData') &&
1545
+ !confirm('Are you sure you want to abandon progress?')) {
1546
+ transition.abort();
1547
+ } else {
1548
+ // Bubble the `willTransition` action so that
1549
+ // parent routes can decide whether or not to abort.
1550
+ return true;
1551
+ }
1552
+ }
1553
+ }
1554
+ ```
1555
+ @property controller
1556
+ @type Controller
1557
+ @since 1.6.0
1558
+ @public
1559
+ */
1560
+ actions: {
1561
+ /**
1562
+ This action is called when one or more query params have changed. Bubbles.
1563
+ @method queryParamsDidChange
1564
+ @param changed {Object} Keys are names of query params that have changed.
1565
+ @param totalPresent {Object} Keys are names of query params that are currently set.
1566
+ @param removed {Object} Keys are names of query params that have been removed.
1567
+ @returns {boolean}
1568
+ @private
1569
+ */
1570
+ queryParamsDidChange(changed, _totalPresent, removed) {
1571
+ // SAFETY: Since `_qp` is protected we can't infer the type
1572
+ let qpMap = get(this, '_qp').map;
1573
+ let totalChanged = Object.keys(changed).concat(Object.keys(removed));
1574
+
1575
+ for (let change of totalChanged) {
1576
+ let qp = qpMap[change];
1577
+
1578
+ if (qp) {
1579
+ let options = this._optionsForQueryParam(qp);
1580
+
1581
+ assert('options exists', options && typeof options === 'object');
1582
+
1583
+ if (get(options, 'refreshModel') && this._router.currentState) {
1584
+ this.refresh();
1585
+ break;
1586
+ }
1587
+ }
1588
+ }
1589
+
1590
+ return true;
1591
+ },
1592
+
1593
+ finalizeQueryParamChange(params, finalParams, transition) {
1594
+ if (this.fullRouteName !== 'application') {
1595
+ return true;
1596
+ } // Transition object is absent for intermediate transitions.
1597
+
1598
+
1599
+ if (!transition) {
1600
+ return;
1601
+ }
1602
+
1603
+ let routeInfos = transition[STATE_SYMBOL].routeInfos;
1604
+ let router = this._router;
1605
+
1606
+ let qpMeta = router._queryParamsFor(routeInfos);
1607
+
1608
+ let changes = router._qpUpdates;
1609
+ let qpUpdated = false;
1610
+ let replaceUrl;
1611
+ stashParamNames(router, routeInfos);
1612
+
1613
+ for (let qp of qpMeta.qps) {
1614
+ let route = qp.route;
1615
+ let controller = route.controller;
1616
+ let presentKey = qp.urlKey in params && qp.urlKey; // Do a reverse lookup to see if the changed query
1617
+ // param URL key corresponds to a QP property on
1618
+ // this controller.
1619
+
1620
+ let value;
1621
+ let svalue;
1622
+
1623
+ if (changes.has(qp.urlKey)) {
1624
+ // Value updated in/before setupController
1625
+ value = get(controller, qp.prop);
1626
+ svalue = route.serializeQueryParam(value, qp.urlKey, qp.type);
1627
+ } else {
1628
+ if (presentKey) {
1629
+ svalue = params[presentKey];
1630
+
1631
+ if (svalue !== undefined) {
1632
+ value = route.deserializeQueryParam(svalue, qp.urlKey, qp.type);
1633
+ }
1634
+ } else {
1635
+ // No QP provided; use default value.
1636
+ svalue = qp.serializedDefaultValue;
1637
+ value = copyDefaultValue(qp.defaultValue);
1638
+ }
1639
+ } // SAFETY: Since `_qp` is protected we can't infer the type
1640
+
1641
+
1642
+ controller._qpDelegate = get(route, '_qp').states.inactive;
1643
+ let thisQueryParamChanged = svalue !== qp.serializedValue;
1644
+
1645
+ if (thisQueryParamChanged) {
1646
+ if (transition.queryParamsOnly && replaceUrl !== false) {
1647
+ let options = route._optionsForQueryParam(qp);
1648
+
1649
+ let replaceConfigValue = get(options, 'replace');
1650
+
1651
+ if (replaceConfigValue) {
1652
+ replaceUrl = true;
1653
+ } else if (replaceConfigValue === false) {
1654
+ // Explicit pushState wins over any other replaceStates.
1655
+ replaceUrl = false;
1656
+ }
1657
+ }
1658
+
1659
+ set(controller, qp.prop, value);
1660
+ qpUpdated = true;
1661
+ } // Stash current serialized value of controller.
1662
+
1663
+
1664
+ qp.serializedValue = svalue;
1665
+ let thisQueryParamHasDefaultValue = qp.serializedDefaultValue === svalue;
1666
+
1667
+ if (!thisQueryParamHasDefaultValue) {
1668
+ finalParams.push({
1669
+ value: svalue,
1670
+ visible: true,
1671
+ key: presentKey || qp.urlKey
1672
+ });
1673
+ }
1674
+ } // Some QPs have been updated, and those changes need to be propogated
1675
+ // immediately. Eventually, we should work on making this async somehow.
1676
+
1677
+
1678
+ if (qpUpdated === true) {
1679
+ flushAsyncObservers(false);
1680
+ }
1681
+
1682
+ if (replaceUrl) {
1683
+ transition.method('replace');
1684
+ }
1685
+
1686
+ qpMeta.qps.forEach(qp => {
1687
+ // SAFETY: Since `_qp` is protected we can't infer the type
1688
+ let routeQpMeta = get(qp.route, '_qp');
1689
+ let finalizedController = qp.route.controller;
1690
+ finalizedController['_qpDelegate'] = get(routeQpMeta, 'states.active');
1691
+ });
1692
+
1693
+ router._qpUpdates.clear();
1694
+
1695
+ return;
1696
+ }
1697
+
1698
+ }
1699
+ });
1700
+ export default Route;