ember-source 4.3.0-alpha.3 → 4.4.0-alpha.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.
- package/CHANGELOG.md +6 -2
- package/blueprints/acceptance-test/mocha-files/tests/acceptance/__name__-test.js +4 -4
- package/blueprints/acceptance-test/mocha-rfc-232-files/tests/acceptance/__name__-test.js +2 -2
- package/blueprints/acceptance-test/qunit-files/tests/acceptance/__name__-test.js +2 -2
- package/blueprints/acceptance-test/qunit-rfc-232-files/tests/acceptance/__name__-test.js +2 -2
- package/blueprints/component/index.js +2 -2
- package/blueprints/component-class/index.js +2 -2
- package/blueprints/component-test/mocha-0.12-files/__root__/__testType__/__path__/__test__.js +4 -4
- package/blueprints/component-test/mocha-files/__root__/__testType__/__path__/__test__.js +7 -5
- package/blueprints/component-test/mocha-rfc-232-files/__root__/__testType__/__path__/__test__.js +4 -4
- package/blueprints/component-test/qunit-files/__root__/__testType__/__path__/__test__.js +4 -4
- package/blueprints/component-test/qunit-rfc-232-files/__root__/__testType__/__path__/__test__.js +4 -4
- package/blueprints/controller/files/__root__/__path__/__name__.js +1 -2
- package/blueprints/controller-test/mocha-0.12-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/controller-test/mocha-files/__root__/__testType__/__path__/__test__.js +5 -3
- package/blueprints/controller-test/mocha-rfc-232-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/controller-test/qunit-files/__root__/__testType__/__path__/__test__.js +1 -1
- package/blueprints/controller-test/qunit-rfc-232-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/helper/files/__root__/__collection__/__name__.js +1 -1
- package/blueprints/helper/mu-files/__root__/__collection__/__name__.js +1 -1
- package/blueprints/helper-test/mocha-0.12-files/__root__/__testType__/__collection__/__name__-test.js +3 -3
- package/blueprints/helper-test/mocha-files/__root__/__testType__/__collection__/__name__-test.js +6 -4
- package/blueprints/helper-test/mocha-rfc-232-files/__root__/__testType__/__collection__/__name__-test.js +2 -2
- package/blueprints/helper-test/qunit-files/__root__/__testType__/__collection__/__name__-test.js +2 -2
- package/blueprints/helper-test/qunit-rfc-232-files/__root__/__testType__/__collection__/__name__-test.js +2 -2
- package/blueprints/initializer/files/__root__/initializers/__name__.js +2 -3
- package/blueprints/initializer-test/mocha-files/__root__/__testType__/__path__/__name__-test.js +6 -7
- package/blueprints/initializer-test/mocha-rfc-232-files/__root__/__testType__/__path__/__name__-test.js +5 -5
- package/blueprints/initializer-test/qunit-files/__root__/__testType__/__path__/__name__-test.js +3 -4
- package/blueprints/instance-initializer/files/__root__/instance-initializers/__name__.js +2 -3
- package/blueprints/instance-initializer-test/mocha-files/__root__/__testType__/__path__/__name__-test.js +5 -5
- package/blueprints/instance-initializer-test/mocha-rfc-232-files/__root__/__testType__/__path__/__name__-test.js +5 -5
- package/blueprints/instance-initializer-test/qunit-files/__root__/__testType__/__path__/__name__-test.js +2 -2
- package/blueprints/mixin/files/__root__/mixins/__name__.js +1 -2
- package/blueprints/mixin-test/mocha-files/__root__/__testType__/__name__-test.js +2 -2
- package/blueprints/mixin-test/mocha-rfc-232-files/__root__/__testType__/__name__-test.js +2 -2
- package/blueprints/mixin-test/qunit-files/__root__/__testType__/__name__-test.js +1 -1
- package/blueprints/mixin-test/qunit-rfc-232-files/__root__/__testType__/__name__-test.js +1 -1
- package/blueprints/route/files/__root__/__path__/__name__.js +2 -2
- package/blueprints/route-test/mocha-0.12-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/route-test/mocha-files/__root__/__testType__/__path__/__test__.js +5 -3
- package/blueprints/route-test/mocha-rfc-232-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/route-test/qunit-files/__root__/__testType__/__path__/__test__.js +1 -1
- package/blueprints/route-test/qunit-rfc-232-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/service/files/__root__/__path__/__name__.js +1 -2
- package/blueprints/service-test/mocha-0.12-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/service-test/mocha-files/__root__/__testType__/__path__/__test__.js +5 -3
- package/blueprints/service-test/mocha-rfc-232-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/service-test/qunit-files/__root__/__testType__/__path__/__test__.js +1 -1
- package/blueprints/service-test/qunit-rfc-232-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/util-test/mocha-files/__root__/__testType__/__name__-test.js +2 -2
- package/blueprints/util-test/mocha-rfc-232-files/__root__/__testType__/__name__-test.js +2 -2
- package/blueprints/util-test/qunit-files/__root__/__testType__/__name__-test.js +1 -1
- package/blueprints/util-test/qunit-rfc-232-files/__root__/__testType__/__name__-test.js +2 -3
- package/build-metadata.json +3 -3
- package/dist/dependencies/router_js.js +67 -32
- package/dist/ember-template-compiler.js +1168 -908
- package/dist/ember-template-compiler.map +1 -1
- package/dist/ember-testing.js +76 -43
- package/dist/ember-testing.map +1 -1
- package/dist/ember.debug.js +3206 -2734
- package/dist/ember.debug.map +1 -1
- package/dist/header/license.js +1 -1
- package/dist/packages/@ember/-internals/container/index.js +18 -13
- package/dist/packages/@ember/-internals/glimmer/index.js +128 -67
- package/dist/packages/@ember/-internals/meta/lib/meta.js +8 -9
- package/dist/packages/@ember/-internals/metal/index.js +58 -61
- package/dist/packages/@ember/-internals/routing/lib/ext/controller.js +10 -8
- package/dist/packages/@ember/-internals/routing/lib/services/router.js +155 -191
- package/dist/packages/@ember/-internals/routing/lib/services/routing.js +2 -0
- package/dist/packages/@ember/-internals/routing/lib/system/generate_controller.js +3 -1
- package/dist/packages/@ember/-internals/routing/lib/system/route-info.js +2 -2
- package/dist/packages/@ember/-internals/routing/lib/system/route.js +108 -380
- package/dist/packages/@ember/-internals/routing/lib/system/router.js +65 -46
- package/dist/packages/@ember/-internals/routing/lib/utils.js +33 -21
- package/dist/packages/@ember/-internals/runtime/lib/mixins/action_handler.js +32 -32
- package/dist/packages/@ember/-internals/runtime/lib/mixins/container_proxy.js +29 -29
- package/dist/packages/@ember/-internals/runtime/lib/mixins/registry_proxy.js +51 -50
- package/dist/packages/@ember/-internals/utils/index.js +3 -1
- package/dist/packages/@ember/-internals/views/lib/system/utils.js +1 -0
- package/dist/packages/@ember/application/instance.js +3 -3
- package/dist/packages/@ember/canary-features/index.js +0 -10
- package/dist/packages/@ember/controller/index.js +3 -54
- package/dist/packages/@ember/debug/lib/capture-render-tree.js +2 -0
- package/dist/packages/@ember/instrumentation/index.js +9 -13
- package/dist/packages/@ember/routing/router-service.js +1 -0
- package/dist/packages/@ember/service/index.js +6 -73
- package/dist/packages/ember/index.js +3 -14
- package/dist/packages/ember/version.js +1 -1
- package/docs/data.json +556 -504
- package/package.json +13 -13
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { privatize as P } from '@ember/-internals/container';
|
|
2
2
|
import { computed, get, set } from '@ember/-internals/metal';
|
|
3
3
|
import { getOwner } from '@ember/-internals/owner';
|
|
4
|
+
import { BucketCache } from '@ember/-internals/routing';
|
|
4
5
|
import { A as emberA, Evented, Object as EmberObject, typeOf } from '@ember/-internals/runtime';
|
|
5
6
|
import { assert, deprecate, info } from '@ember/debug';
|
|
6
7
|
import EmberError from '@ember/error';
|
|
@@ -11,7 +12,12 @@ import { calculateCacheKey, extractRouteArgs, getActiveTargetName, resemblesURL
|
|
|
11
12
|
import DSL from './dsl';
|
|
12
13
|
import { defaultSerialize, getFullQueryParams, hasDefaultSerialize, ROUTE_CONNECTIONS } from './route';
|
|
13
14
|
import RouterState from './router_state';
|
|
15
|
+
/**
|
|
16
|
+
@module @ember/routing
|
|
17
|
+
*/
|
|
18
|
+
|
|
14
19
|
import Router, { logAbort, STATE_SYMBOL } from 'router_js';
|
|
20
|
+
import EngineInstance from '@ember/engine/instance';
|
|
15
21
|
|
|
16
22
|
function defaultDidTransition(infos) {
|
|
17
23
|
updatePaths(this);
|
|
@@ -73,7 +79,7 @@ const {
|
|
|
73
79
|
|
|
74
80
|
class EmberRouter extends EmberObject.extend(Evented) {
|
|
75
81
|
constructor(owner) {
|
|
76
|
-
super(
|
|
82
|
+
super(owner);
|
|
77
83
|
this._didSetupRouter = false;
|
|
78
84
|
this._initialTransitionStarted = false;
|
|
79
85
|
this.currentURL = null;
|
|
@@ -95,7 +101,7 @@ class EmberRouter extends EmberObject.extend(Evented) {
|
|
|
95
101
|
|
|
96
102
|
this.namespace = owner.lookup('application:main');
|
|
97
103
|
let bucketCache = owner.lookup(P`-bucket-cache:main`);
|
|
98
|
-
assert('BUG: BucketCache should always be present', bucketCache
|
|
104
|
+
assert('BUG: BucketCache should always be present', bucketCache instanceof BucketCache);
|
|
99
105
|
this._bucketCache = bucketCache;
|
|
100
106
|
let routerService = owner.lookup('service:router');
|
|
101
107
|
assert('BUG: RouterService should always be present', routerService !== undefined);
|
|
@@ -166,7 +172,9 @@ class EmberRouter extends EmberObject.extend(Evented) {
|
|
|
166
172
|
let name, nameParts, oldNameParts;
|
|
167
173
|
|
|
168
174
|
for (let i = 1; i < routeInfos.length; i++) {
|
|
169
|
-
|
|
175
|
+
let routeInfo = routeInfos[i];
|
|
176
|
+
assert('has routeInfo', routeInfo);
|
|
177
|
+
name = routeInfo.name;
|
|
170
178
|
nameParts = name.split('.');
|
|
171
179
|
oldNameParts = slice.call(path);
|
|
172
180
|
|
|
@@ -472,8 +480,8 @@ class EmberRouter extends EmberObject.extend(Evented) {
|
|
|
472
480
|
let defaultParentState;
|
|
473
481
|
let liveRoutes = null;
|
|
474
482
|
|
|
475
|
-
for (let
|
|
476
|
-
let route =
|
|
483
|
+
for (let routeInfo of routeInfos) {
|
|
484
|
+
let route = routeInfo.route;
|
|
477
485
|
let connections = ROUTE_CONNECTIONS.get(route);
|
|
478
486
|
let ownState;
|
|
479
487
|
|
|
@@ -549,9 +557,8 @@ class EmberRouter extends EmberObject.extend(Evented) {
|
|
|
549
557
|
/**
|
|
550
558
|
Transition the application into another route. The route may
|
|
551
559
|
be either a single route or route path:
|
|
552
|
-
See [transitionTo](/ember/release/classes/Route/methods/transitionTo?anchor=transitionTo) for more info.
|
|
553
560
|
@method transitionTo
|
|
554
|
-
@param {String} name the name of the route or a URL
|
|
561
|
+
@param {String} [name] the name of the route or a URL
|
|
555
562
|
@param {...Object} models the model(s) or identifier(s) to be used while
|
|
556
563
|
transitioning to the route.
|
|
557
564
|
@param {Object} [options] optional hash with a queryParams property
|
|
@@ -592,6 +599,23 @@ class EmberRouter extends EmberObject.extend(Evented) {
|
|
|
592
599
|
}
|
|
593
600
|
}
|
|
594
601
|
}
|
|
602
|
+
/**
|
|
603
|
+
Similar to `transitionTo`, but instead of adding the destination to the browser's URL history,
|
|
604
|
+
it replaces the entry for the current route.
|
|
605
|
+
When the user clicks the "back" button in the browser, there will be fewer steps.
|
|
606
|
+
This is most commonly used to manage redirects in a way that does not cause confusing additions
|
|
607
|
+
to the user's browsing history.
|
|
608
|
+
@method replaceWith
|
|
609
|
+
@param {String} [name] the name of the route or a URL
|
|
610
|
+
@param {...Object} models the model(s) or identifier(s) to be used while
|
|
611
|
+
transitioning to the route.
|
|
612
|
+
@param {Object} [options] optional hash with a queryParams property
|
|
613
|
+
containing a mapping of query parameters
|
|
614
|
+
@return {Transition} the transition object associated with this
|
|
615
|
+
attempted transition
|
|
616
|
+
@public
|
|
617
|
+
*/
|
|
618
|
+
|
|
595
619
|
|
|
596
620
|
replaceWith(...args) {
|
|
597
621
|
return this.transitionTo(...args).method('replace');
|
|
@@ -677,8 +701,11 @@ class EmberRouter extends EmberObject.extend(Evented) {
|
|
|
677
701
|
let instances = this._engineInstances;
|
|
678
702
|
|
|
679
703
|
for (let name in instances) {
|
|
680
|
-
|
|
681
|
-
|
|
704
|
+
let instance = instances[name];
|
|
705
|
+
assert('has instance', instance);
|
|
706
|
+
|
|
707
|
+
for (let id in instance) {
|
|
708
|
+
run(instance[id], 'destroy');
|
|
682
709
|
}
|
|
683
710
|
}
|
|
684
711
|
}
|
|
@@ -1000,12 +1027,11 @@ class EmberRouter extends EmberObject.extend(Evented) {
|
|
|
1000
1027
|
let qps = [];
|
|
1001
1028
|
let qpsByUrlKey = DEBUG ? {} : null;
|
|
1002
1029
|
let qpMeta;
|
|
1003
|
-
let qp;
|
|
1004
1030
|
let urlKey;
|
|
1005
1031
|
let qpOther;
|
|
1006
1032
|
|
|
1007
|
-
for (let
|
|
1008
|
-
qpMeta = this._getQPMeta(
|
|
1033
|
+
for (let routeInfo of routeInfos) {
|
|
1034
|
+
qpMeta = this._getQPMeta(routeInfo);
|
|
1009
1035
|
|
|
1010
1036
|
if (!qpMeta) {
|
|
1011
1037
|
shouldCache = false;
|
|
@@ -1013,9 +1039,7 @@ class EmberRouter extends EmberObject.extend(Evented) {
|
|
|
1013
1039
|
} // Loop over each QP to make sure we don't have any collisions by urlKey
|
|
1014
1040
|
|
|
1015
1041
|
|
|
1016
|
-
for (let
|
|
1017
|
-
qp = qpMeta.qps[i];
|
|
1018
|
-
|
|
1042
|
+
for (let qp of qpMeta.qps) {
|
|
1019
1043
|
if (DEBUG) {
|
|
1020
1044
|
urlKey = qp.urlKey;
|
|
1021
1045
|
qpOther = qpsByUrlKey[urlKey];
|
|
@@ -1061,19 +1085,15 @@ class EmberRouter extends EmberObject.extend(Evented) {
|
|
|
1061
1085
|
let routeInfos = state.routeInfos;
|
|
1062
1086
|
let qpMeta;
|
|
1063
1087
|
|
|
1064
|
-
for (let
|
|
1065
|
-
qpMeta = this._getQPMeta(
|
|
1088
|
+
for (let routeInfo of routeInfos) {
|
|
1089
|
+
qpMeta = this._getQPMeta(routeInfo);
|
|
1066
1090
|
|
|
1067
1091
|
if (!qpMeta) {
|
|
1068
1092
|
continue;
|
|
1069
1093
|
}
|
|
1070
1094
|
|
|
1071
|
-
let qp
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
for (let j = 0, qpLen = qpMeta.qps.length; j < qpLen; ++j) {
|
|
1075
|
-
qp = qpMeta.qps[j];
|
|
1076
|
-
presentProp = qp.prop in queryParams && qp.prop || qp.scopedPropertyName in queryParams && qp.scopedPropertyName || qp.urlKey in queryParams && qp.urlKey;
|
|
1095
|
+
for (let qp of qpMeta.qps) {
|
|
1096
|
+
let presentProp = qp.prop in queryParams && qp.prop || qp.scopedPropertyName in queryParams && qp.scopedPropertyName || qp.urlKey in queryParams && qp.urlKey;
|
|
1077
1097
|
|
|
1078
1098
|
if (presentProp) {
|
|
1079
1099
|
if (presentProp !== qp.scopedPropertyName) {
|
|
@@ -1103,15 +1123,17 @@ class EmberRouter extends EmberObject.extend(Evented) {
|
|
|
1103
1123
|
let qp;
|
|
1104
1124
|
let presentProp;
|
|
1105
1125
|
|
|
1106
|
-
for (let
|
|
1107
|
-
qpMeta = this._getQPMeta(
|
|
1126
|
+
for (let routeInfo of routeInfos) {
|
|
1127
|
+
qpMeta = this._getQPMeta(routeInfo);
|
|
1108
1128
|
|
|
1109
1129
|
if (!qpMeta) {
|
|
1110
1130
|
continue;
|
|
1111
|
-
}
|
|
1131
|
+
} // Needs to stay for index loop to avoid throwIfClosureRequired
|
|
1132
|
+
|
|
1112
1133
|
|
|
1113
1134
|
for (let j = 0, qpLen = qpMeta.qps.length; j < qpLen; ++j) {
|
|
1114
1135
|
qp = qpMeta.qps[j];
|
|
1136
|
+
assert('expected qp', qp);
|
|
1115
1137
|
presentProp = qp.prop in queryParams && qp.prop || qp.scopedPropertyName in queryParams && qp.scopedPropertyName || qp.urlKey in queryParams && qp.urlKey;
|
|
1116
1138
|
assert(`You passed the \`${presentProp}\` query parameter during a transition into ${qp.route.routeName}, please update to ${qp.urlKey}`, function () {
|
|
1117
1139
|
if (qp.urlKey === presentProp || qp.scopedPropertyName === presentProp) {
|
|
@@ -1188,23 +1210,27 @@ class EmberRouter extends EmberObject.extend(Evented) {
|
|
|
1188
1210
|
mountPoint
|
|
1189
1211
|
}) {
|
|
1190
1212
|
let engineInstances = this._engineInstances;
|
|
1213
|
+
let namedInstances = engineInstances[name];
|
|
1191
1214
|
|
|
1192
|
-
if (!
|
|
1193
|
-
|
|
1194
|
-
|
|
1215
|
+
if (!namedInstances) {
|
|
1216
|
+
namedInstances = Object.create(null);
|
|
1217
|
+
engineInstances[name] = namedInstances;
|
|
1218
|
+
} // We just set these!
|
|
1195
1219
|
|
|
1196
|
-
|
|
1220
|
+
|
|
1221
|
+
assert('has namedInstances', namedInstances);
|
|
1222
|
+
let engineInstance = namedInstances[instanceId];
|
|
1197
1223
|
|
|
1198
1224
|
if (!engineInstance) {
|
|
1199
1225
|
let owner = getOwner(this);
|
|
1200
|
-
assert('
|
|
1226
|
+
assert('Expected router to have EngineInstance as owner', owner instanceof EngineInstance);
|
|
1201
1227
|
assert(`You attempted to mount the engine '${name}' in your router map, but the engine can not be found.`, owner.hasRegistration(`engine:${name}`));
|
|
1202
1228
|
engineInstance = owner.buildChildEngineInstance(name, {
|
|
1203
1229
|
routable: true,
|
|
1204
1230
|
mountPoint
|
|
1205
1231
|
});
|
|
1206
1232
|
engineInstance.boot();
|
|
1207
|
-
|
|
1233
|
+
namedInstances[instanceId] = engineInstance;
|
|
1208
1234
|
}
|
|
1209
1235
|
|
|
1210
1236
|
return engineInstance;
|
|
@@ -1231,6 +1257,7 @@ class EmberRouter extends EmberObject.extend(Evented) {
|
|
|
1231
1257
|
function forEachRouteAbove(routeInfos, callback) {
|
|
1232
1258
|
for (let i = routeInfos.length - 1; i >= 0; --i) {
|
|
1233
1259
|
let routeInfo = routeInfos[i];
|
|
1260
|
+
assert('has routeInfo', routeInfo);
|
|
1234
1261
|
let route = routeInfo.route; // routeInfo.handler being `undefined` generally means either:
|
|
1235
1262
|
//
|
|
1236
1263
|
// 1. an error occurred during creation of the route in question
|
|
@@ -1433,6 +1460,7 @@ export function triggerEvent(routeInfos, ignoreFailure, name, args) {
|
|
|
1433
1460
|
|
|
1434
1461
|
for (let i = routeInfos.length - 1; i >= 0; i--) {
|
|
1435
1462
|
routeInfo = routeInfos[i];
|
|
1463
|
+
assert('has routeInfo', routeInfo);
|
|
1436
1464
|
handler = routeInfo.route;
|
|
1437
1465
|
actionHandler = handler && handler.actions && handler.actions[name];
|
|
1438
1466
|
|
|
@@ -1470,9 +1498,8 @@ function calculatePostTransitionState(emberRouter, leafRouteName, contexts) {
|
|
|
1470
1498
|
params
|
|
1471
1499
|
} = state;
|
|
1472
1500
|
|
|
1473
|
-
for (let
|
|
1474
|
-
|
|
1475
|
-
|
|
1501
|
+
for (let routeInfo of routeInfos) {
|
|
1502
|
+
// If the routeInfo is not resolved, we serialize the context into params
|
|
1476
1503
|
if (!routeInfo.isResolved) {
|
|
1477
1504
|
params[routeInfo.name] = routeInfo.serialize(routeInfo.context);
|
|
1478
1505
|
} else {
|
|
@@ -1492,23 +1519,15 @@ function updatePaths(router) {
|
|
|
1492
1519
|
|
|
1493
1520
|
let path = EmberRouter._routePath(infos);
|
|
1494
1521
|
|
|
1495
|
-
let
|
|
1522
|
+
let info = infos[infos.length - 1];
|
|
1523
|
+
assert('expected info', info);
|
|
1524
|
+
let currentRouteName = info.name;
|
|
1496
1525
|
let location = router.location;
|
|
1497
1526
|
assert('expected location to not be a string', typeof location !== 'string');
|
|
1498
1527
|
let currentURL = location.getURL();
|
|
1499
1528
|
set(router, 'currentPath', path);
|
|
1500
1529
|
set(router, 'currentRouteName', currentRouteName);
|
|
1501
1530
|
set(router, 'currentURL', currentURL);
|
|
1502
|
-
let owner = getOwner(router);
|
|
1503
|
-
assert('Router is unexpectedly missing an owner', owner);
|
|
1504
|
-
let appController = owner.lookup('controller:application');
|
|
1505
|
-
|
|
1506
|
-
if (!appController) {
|
|
1507
|
-
// appController might not exist when top-level loading/error
|
|
1508
|
-
// substates have been entered since ApplicationRoute hasn't
|
|
1509
|
-
// actually been entered at that point.
|
|
1510
|
-
return;
|
|
1511
|
-
}
|
|
1512
1531
|
}
|
|
1513
1532
|
|
|
1514
1533
|
function didBeginTransition(transition, router) {
|
|
@@ -1,26 +1,33 @@
|
|
|
1
1
|
import { get } from '@ember/-internals/metal';
|
|
2
2
|
import { getOwner } from '@ember/-internals/owner';
|
|
3
3
|
import { assert, deprecate } from '@ember/debug';
|
|
4
|
+
import EngineInstance from '@ember/engine/instance';
|
|
4
5
|
import EmberError from '@ember/error';
|
|
5
6
|
import { STATE_SYMBOL } from 'router_js';
|
|
6
7
|
const ALL_PERIODS_REGEX = /\./g;
|
|
7
8
|
export function extractRouteArgs(args) {
|
|
9
|
+
// SAFETY: This should just be the same thing
|
|
8
10
|
args = args.slice();
|
|
9
|
-
let
|
|
11
|
+
let possibleOptions = args[args.length - 1];
|
|
10
12
|
let queryParams;
|
|
11
13
|
|
|
12
|
-
if (
|
|
13
|
-
|
|
14
|
+
if (isRouteOptions(possibleOptions)) {
|
|
15
|
+
args.pop(); // Remove options
|
|
16
|
+
|
|
17
|
+
queryParams = possibleOptions.queryParams;
|
|
14
18
|
} else {
|
|
15
|
-
// Not query params so return to the array
|
|
16
|
-
args.push(possibleQueryParams);
|
|
17
19
|
queryParams = {};
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let routeName;
|
|
23
|
+
|
|
24
|
+
if (typeof args[0] === 'string') {
|
|
25
|
+
routeName = args.shift(); // We just checked this!
|
|
26
|
+
|
|
27
|
+
assert('routeName is a string', typeof routeName === 'string');
|
|
28
|
+
} // SAFTEY: We removed the name and options if they existed, only models left.
|
|
21
29
|
|
|
22
30
|
|
|
23
|
-
let routeName = args.shift();
|
|
24
31
|
let models = args;
|
|
25
32
|
return {
|
|
26
33
|
routeName,
|
|
@@ -30,7 +37,9 @@ export function extractRouteArgs(args) {
|
|
|
30
37
|
}
|
|
31
38
|
export function getActiveTargetName(router) {
|
|
32
39
|
let routeInfos = router.activeTransition ? router.activeTransition[STATE_SYMBOL].routeInfos : router.state.routeInfos;
|
|
33
|
-
|
|
40
|
+
let lastRouteInfo = routeInfos[routeInfos.length - 1];
|
|
41
|
+
assert('has last route info', lastRouteInfo);
|
|
42
|
+
return lastRouteInfo.name;
|
|
34
43
|
}
|
|
35
44
|
export function stashParamNames(router, routeInfos) {
|
|
36
45
|
if (routeInfos['_namesStashed']) {
|
|
@@ -41,7 +50,9 @@ export function stashParamNames(router, routeInfos) {
|
|
|
41
50
|
// Hopefully we can remove this in the future.
|
|
42
51
|
|
|
43
52
|
|
|
44
|
-
let
|
|
53
|
+
let routeInfo = routeInfos[routeInfos.length - 1];
|
|
54
|
+
assert('has route info', routeInfo);
|
|
55
|
+
let targetRouteName = routeInfo.name;
|
|
45
56
|
|
|
46
57
|
let recogHandlers = router._routerMicrolib.recognizer.handlersFor(targetRouteName);
|
|
47
58
|
|
|
@@ -49,6 +60,7 @@ export function stashParamNames(router, routeInfos) {
|
|
|
49
60
|
|
|
50
61
|
for (let i = 0; i < routeInfos.length; ++i) {
|
|
51
62
|
let routeInfo = routeInfos[i];
|
|
63
|
+
assert('has route info', routeInfo);
|
|
52
64
|
let names = recogHandlers[i].names;
|
|
53
65
|
|
|
54
66
|
if (names.length) {
|
|
@@ -56,7 +68,7 @@ export function stashParamNames(router, routeInfos) {
|
|
|
56
68
|
}
|
|
57
69
|
|
|
58
70
|
routeInfo['_names'] = names;
|
|
59
|
-
let route = routeInfo.route;
|
|
71
|
+
let route = routeInfo.route; // SAFETY: This cast should be idential. I don't understand why it is needed.
|
|
60
72
|
|
|
61
73
|
route._stashNames(routeInfo, dynamicParent);
|
|
62
74
|
}
|
|
@@ -94,9 +106,7 @@ function _calculateCacheValuePrefix(prefix, part) {
|
|
|
94
106
|
export function calculateCacheKey(prefix, parts = [], values) {
|
|
95
107
|
let suffixes = '';
|
|
96
108
|
|
|
97
|
-
for (let
|
|
98
|
-
let part = parts[i];
|
|
99
|
-
|
|
109
|
+
for (let part of parts) {
|
|
100
110
|
let cacheValuePrefix = _calculateCacheValuePrefix(prefix, part);
|
|
101
111
|
|
|
102
112
|
let value;
|
|
@@ -151,8 +161,8 @@ export function calculateCacheKey(prefix, parts = [], values) {
|
|
|
151
161
|
export function normalizeControllerQueryParams(queryParams) {
|
|
152
162
|
let qpMap = {};
|
|
153
163
|
|
|
154
|
-
for (let
|
|
155
|
-
accumulateQueryParamDescriptors(
|
|
164
|
+
for (let queryParam of queryParams) {
|
|
165
|
+
accumulateQueryParamDescriptors(queryParam, qpMap);
|
|
156
166
|
}
|
|
157
167
|
|
|
158
168
|
return qpMap;
|
|
@@ -208,12 +218,14 @@ export function resemblesURL(str) {
|
|
|
208
218
|
*/
|
|
209
219
|
|
|
210
220
|
export function prefixRouteNameArg(route, args) {
|
|
211
|
-
let routeName
|
|
221
|
+
let routeName;
|
|
212
222
|
let owner = getOwner(route);
|
|
213
|
-
assert('
|
|
223
|
+
assert('Expected route to have EngineInstance as owner', owner instanceof EngineInstance);
|
|
214
224
|
let prefix = owner.mountPoint; // only alter the routeName if it's actually referencing a route.
|
|
215
225
|
|
|
216
|
-
if (owner.routable && typeof
|
|
226
|
+
if (owner.routable && typeof args[0] === 'string') {
|
|
227
|
+
routeName = args[0];
|
|
228
|
+
|
|
217
229
|
if (resemblesURL(routeName)) {
|
|
218
230
|
throw new EmberError('Programmatic transitions by URL cannot be used within an Engine. Please use the route name instead.');
|
|
219
231
|
} else {
|
|
@@ -260,7 +272,7 @@ export function deprecateTransitionMethods(frameworkClass, methodName) {
|
|
|
260
272
|
});
|
|
261
273
|
}
|
|
262
274
|
|
|
263
|
-
function
|
|
275
|
+
function isRouteOptions(value) {
|
|
264
276
|
if (value && typeof value === 'object') {
|
|
265
277
|
let qps = value.queryParams;
|
|
266
278
|
|
|
@@ -21,16 +21,16 @@ const ActionHandler = Mixin.create({
|
|
|
21
21
|
/**
|
|
22
22
|
The collection of functions, keyed by name, available on this
|
|
23
23
|
`ActionHandler` as action targets.
|
|
24
|
-
|
|
24
|
+
These functions will be invoked when a matching `{{action}}` is triggered
|
|
25
25
|
from within a template and the application's current route is this route.
|
|
26
|
-
|
|
26
|
+
Actions can also be invoked from other parts of your application
|
|
27
27
|
via `ActionHandler#send`.
|
|
28
|
-
|
|
28
|
+
The `actions` hash will inherit action handlers from
|
|
29
29
|
the `actions` hash defined on extended parent classes
|
|
30
30
|
or mixins rather than just replace the entire hash, e.g.:
|
|
31
|
-
|
|
31
|
+
```app/mixins/can-display-banner.js
|
|
32
32
|
import Mixin from '@ember/mixin';
|
|
33
|
-
|
|
33
|
+
export default Mixin.create({
|
|
34
34
|
actions: {
|
|
35
35
|
displayBanner(msg) {
|
|
36
36
|
// ...
|
|
@@ -38,28 +38,28 @@ const ActionHandler = Mixin.create({
|
|
|
38
38
|
}
|
|
39
39
|
});
|
|
40
40
|
```
|
|
41
|
-
|
|
41
|
+
```app/routes/welcome.js
|
|
42
42
|
import Route from '@ember/routing/route';
|
|
43
43
|
import CanDisplayBanner from '../mixins/can-display-banner';
|
|
44
|
-
|
|
44
|
+
export default Route.extend(CanDisplayBanner, {
|
|
45
45
|
actions: {
|
|
46
46
|
playMusic() {
|
|
47
47
|
// ...
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
|
-
|
|
51
|
+
// `WelcomeRoute`, when active, will be able to respond
|
|
52
52
|
// to both actions, since the actions hash is merged rather
|
|
53
53
|
// then replaced when extending mixins / parent classes.
|
|
54
54
|
this.send('displayBanner');
|
|
55
55
|
this.send('playMusic');
|
|
56
56
|
```
|
|
57
|
-
|
|
57
|
+
Within a Controller, Route or Component's action handler,
|
|
58
58
|
the value of the `this` context is the Controller, Route or
|
|
59
59
|
Component object:
|
|
60
|
-
|
|
60
|
+
```app/routes/song.js
|
|
61
61
|
import Route from '@ember/routing/route';
|
|
62
|
-
|
|
62
|
+
export default Route.extend({
|
|
63
63
|
actions: {
|
|
64
64
|
myAction() {
|
|
65
65
|
this.controllerFor("song");
|
|
@@ -69,13 +69,13 @@ const ActionHandler = Mixin.create({
|
|
|
69
69
|
}
|
|
70
70
|
});
|
|
71
71
|
```
|
|
72
|
-
|
|
72
|
+
It is also possible to call `this._super(...arguments)` from within an
|
|
73
73
|
action handler if it overrides a handler defined on a parent
|
|
74
74
|
class or mixin:
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
Take for example the following routes:
|
|
76
|
+
```app/mixins/debug-route.js
|
|
77
77
|
import Mixin from '@ember/mixin';
|
|
78
|
-
|
|
78
|
+
export default Mixin.create({
|
|
79
79
|
actions: {
|
|
80
80
|
debugRouteInformation() {
|
|
81
81
|
console.debug("It's a-me, console.debug!");
|
|
@@ -83,54 +83,54 @@ const ActionHandler = Mixin.create({
|
|
|
83
83
|
}
|
|
84
84
|
});
|
|
85
85
|
```
|
|
86
|
-
|
|
86
|
+
```app/routes/annoying-debug.js
|
|
87
87
|
import Route from '@ember/routing/route';
|
|
88
88
|
import DebugRoute from '../mixins/debug-route';
|
|
89
|
-
|
|
89
|
+
export default Route.extend(DebugRoute, {
|
|
90
90
|
actions: {
|
|
91
91
|
debugRouteInformation() {
|
|
92
92
|
// also call the debugRouteInformation of mixed in DebugRoute
|
|
93
93
|
this._super(...arguments);
|
|
94
|
-
|
|
94
|
+
// show additional annoyance
|
|
95
95
|
window.alert(...);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
});
|
|
99
99
|
```
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
## Bubbling
|
|
101
|
+
By default, an action will stop bubbling once a handler defined
|
|
102
102
|
on the `actions` hash handles it. To continue bubbling the action,
|
|
103
103
|
you must return `true` from the handler:
|
|
104
|
-
|
|
104
|
+
```app/router.js
|
|
105
105
|
Router.map(function() {
|
|
106
106
|
this.route("album", function() {
|
|
107
107
|
this.route("song");
|
|
108
108
|
});
|
|
109
109
|
});
|
|
110
110
|
```
|
|
111
|
-
|
|
111
|
+
```app/routes/album.js
|
|
112
112
|
import Route from '@ember/routing/route';
|
|
113
|
-
|
|
113
|
+
export default Route.extend({
|
|
114
114
|
actions: {
|
|
115
115
|
startPlaying: function() {
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
});
|
|
119
119
|
```
|
|
120
|
-
|
|
120
|
+
```app/routes/album-song.js
|
|
121
121
|
import Route from '@ember/routing/route';
|
|
122
|
-
|
|
122
|
+
export default Route.extend({
|
|
123
123
|
actions: {
|
|
124
124
|
startPlaying() {
|
|
125
125
|
// ...
|
|
126
|
-
|
|
126
|
+
if (actionShouldAlsoBeTriggeredOnParentRoute) {
|
|
127
127
|
return true;
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
});
|
|
132
132
|
```
|
|
133
|
-
|
|
133
|
+
@property actions
|
|
134
134
|
@type Object
|
|
135
135
|
@default null
|
|
136
136
|
@public
|
|
@@ -140,14 +140,14 @@ const ActionHandler = Mixin.create({
|
|
|
140
140
|
Triggers a named action on the `ActionHandler`. Any parameters
|
|
141
141
|
supplied after the `actionName` string will be passed as arguments
|
|
142
142
|
to the action target function.
|
|
143
|
-
|
|
143
|
+
If the `ActionHandler` has its `target` property set, actions may
|
|
144
144
|
bubble to the `target`. Bubbling happens when an `actionName` can
|
|
145
145
|
not be found in the `ActionHandler`'s `actions` hash or if the
|
|
146
146
|
action target function returns `true`.
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
Example
|
|
148
|
+
```app/routes/welcome.js
|
|
149
149
|
import Route from '@ember/routing/route';
|
|
150
|
-
|
|
150
|
+
export default Route.extend({
|
|
151
151
|
actions: {
|
|
152
152
|
playTheme() {
|
|
153
153
|
this.send('playMusic', 'theme.mp3');
|
|
@@ -158,7 +158,7 @@ const ActionHandler = Mixin.create({
|
|
|
158
158
|
}
|
|
159
159
|
});
|
|
160
160
|
```
|
|
161
|
-
|
|
161
|
+
@method send
|
|
162
162
|
@param {String} actionName The action to trigger
|
|
163
163
|
@param {*} context a context to send with the action
|
|
164
164
|
@public
|
|
@@ -15,7 +15,7 @@ import { Mixin } from '@ember/-internals/metal';
|
|
|
15
15
|
let containerProxyMixin = {
|
|
16
16
|
/**
|
|
17
17
|
The container stores state.
|
|
18
|
-
|
|
18
|
+
@private
|
|
19
19
|
@property {Ember.Container} __container__
|
|
20
20
|
*/
|
|
21
21
|
__container__: null,
|
|
@@ -23,16 +23,16 @@ let containerProxyMixin = {
|
|
|
23
23
|
/**
|
|
24
24
|
Returns an object that can be used to provide an owner to a
|
|
25
25
|
manually created instance.
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
Example:
|
|
27
|
+
```
|
|
28
28
|
import { getOwner } from '@ember/application';
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
let owner = getOwner(this);
|
|
30
|
+
User.create(
|
|
31
31
|
owner.ownerInjection(),
|
|
32
32
|
{ username: 'rwjblue' }
|
|
33
33
|
)
|
|
34
34
|
```
|
|
35
|
-
|
|
35
|
+
@public
|
|
36
36
|
@method ownerInjection
|
|
37
37
|
@since 2.3.0
|
|
38
38
|
@return {Object}
|
|
@@ -43,30 +43,30 @@ let containerProxyMixin = {
|
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
Given a fullName return a corresponding instance.
|
|
46
|
-
|
|
46
|
+
The default behavior is for lookup to return a singleton instance.
|
|
47
47
|
The singleton is scoped to the container, allowing multiple containers
|
|
48
48
|
to all have their own locally scoped singletons.
|
|
49
|
-
|
|
49
|
+
```javascript
|
|
50
50
|
let registry = new Registry();
|
|
51
51
|
let container = registry.container();
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
registry.register('api:twitter', Twitter);
|
|
53
|
+
let twitter = container.lookup('api:twitter');
|
|
54
|
+
twitter instanceof Twitter; // => true
|
|
55
|
+
// by default the container will return singletons
|
|
56
56
|
let twitter2 = container.lookup('api:twitter');
|
|
57
57
|
twitter2 instanceof Twitter; // => true
|
|
58
|
-
|
|
58
|
+
twitter === twitter2; //=> true
|
|
59
59
|
```
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
If singletons are not wanted an optional flag can be provided at lookup.
|
|
61
|
+
```javascript
|
|
62
62
|
let registry = new Registry();
|
|
63
63
|
let container = registry.container();
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
registry.register('api:twitter', Twitter);
|
|
65
|
+
let twitter = container.lookup('api:twitter', { singleton: false });
|
|
66
66
|
let twitter2 = container.lookup('api:twitter', { singleton: false });
|
|
67
|
-
|
|
67
|
+
twitter === twitter2; //=> false
|
|
68
68
|
```
|
|
69
|
-
|
|
69
|
+
@public
|
|
70
70
|
@method lookup
|
|
71
71
|
@param {String} fullName
|
|
72
72
|
@param {Object} options
|
|
@@ -91,32 +91,32 @@ let containerProxyMixin = {
|
|
|
91
91
|
|
|
92
92
|
/**
|
|
93
93
|
Given a fullName return a factory manager.
|
|
94
|
-
|
|
94
|
+
This method returns a manager which can be used for introspection of the
|
|
95
95
|
factory's class or for the creation of factory instances with initial
|
|
96
96
|
properties. The manager is an object with the following properties:
|
|
97
|
-
|
|
97
|
+
* `class` - The registered or resolved class.
|
|
98
98
|
* `create` - A function that will create an instance of the class with
|
|
99
99
|
any dependencies injected.
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
For example:
|
|
101
|
+
```javascript
|
|
102
102
|
import { getOwner } from '@ember/application';
|
|
103
|
-
|
|
103
|
+
let owner = getOwner(otherInstance);
|
|
104
104
|
// the owner is commonly the `applicationInstance`, and can be accessed via
|
|
105
105
|
// an instance initializer.
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
let factory = owner.factoryFor('service:bespoke');
|
|
107
|
+
factory.class;
|
|
108
108
|
// The registered or resolved class. For example when used with an Ember-CLI
|
|
109
109
|
// app, this would be the default export from `app/services/bespoke.js`.
|
|
110
|
-
|
|
110
|
+
let instance = factory.create({
|
|
111
111
|
someProperty: 'an initial property value'
|
|
112
112
|
});
|
|
113
113
|
// Create an instance with any injections and the passed options as
|
|
114
114
|
// initial properties.
|
|
115
115
|
```
|
|
116
|
-
|
|
116
|
+
Any instances created via the factory's `.create()` method *must* be destroyed
|
|
117
117
|
manually by the caller of `.create()`. Typically, this is done during the creating
|
|
118
118
|
objects own `destroy` or `willDestroy` methods.
|
|
119
|
-
|
|
119
|
+
@public
|
|
120
120
|
@method factoryFor
|
|
121
121
|
@param {String} fullName
|
|
122
122
|
@param {Object} options
|