ember-source 4.1.0-alpha.6 → 4.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +81 -63
- package/blueprints/acceptance-test/qunit-files/tests/acceptance/__name__-test.js +1 -1
- package/blueprints/acceptance-test/qunit-rfc-232-files/tests/acceptance/__name__-test.js +1 -1
- package/blueprints/component-test/qunit-files/__root__/__testType__/__path__/__test__.js +3 -3
- package/blueprints/helper-test/index.js +4 -22
- package/blueprints/helper-test/mocha-0.12-files/__root__/__testType__/__collection__/__name__-test.js +1 -13
- package/blueprints/helper-test/mocha-files/__root__/__testType__/__collection__/__name__-test.js +0 -13
- package/blueprints/helper-test/mocha-rfc-232-files/__root__/__testType__/__collection__/__name__-test.js +2 -12
- package/blueprints/helper-test/qunit-files/__root__/__testType__/__collection__/__name__-test.js +2 -13
- package/blueprints/helper-test/qunit-rfc-232-files/__root__/__testType__/__collection__/__name__-test.js +2 -14
- package/build-metadata.json +3 -3
- package/dist/dependencies/@glimmer/manager.js +19 -98
- package/dist/dependencies/@glimmer/opcode-compiler.js +9 -146
- package/dist/dependencies/@glimmer/runtime.js +1 -55
- package/dist/dependencies/@glimmer/validator.js +19 -51
- package/dist/ember-template-compiler.js +366 -691
- package/dist/ember-template-compiler.map +1 -1
- package/dist/ember-testing.js +1 -1
- package/dist/ember-testing.map +1 -1
- package/dist/ember.debug.js +3259 -6349
- package/dist/ember.debug.map +1 -1
- package/dist/header/license.js +1 -1
- package/dist/packages/@ember/-internals/environment/index.js +0 -15
- package/dist/packages/@ember/-internals/glimmer/index.js +4815 -6763
- package/dist/packages/@ember/-internals/metal/index.js +57 -103
- package/dist/packages/@ember/-internals/routing/lib/location/api.js +10 -1
- package/dist/packages/@ember/-internals/routing/lib/location/none_location.js +7 -2
- package/dist/packages/@ember/-internals/routing/lib/services/router.js +1 -1
- package/dist/packages/@ember/-internals/routing/lib/services/routing.js +1 -1
- package/dist/packages/@ember/-internals/routing/lib/system/route.js +3 -42
- package/dist/packages/@ember/-internals/routing/lib/system/router.js +36 -46
- package/dist/packages/@ember/-internals/runtime/lib/mixins/array.js +2 -173
- package/dist/packages/@ember/-internals/runtime/lib/mixins/target_action_support.js +3 -43
- package/dist/packages/@ember/-internals/runtime/lib/system/array_proxy.js +8 -15
- package/dist/packages/@ember/-internals/utils/index.js +0 -3
- package/dist/packages/@ember/-internals/views/index.js +0 -1
- package/dist/packages/@ember/-internals/views/lib/mixins/view_support.js +4 -4
- package/dist/packages/@ember/application/lib/application.js +7 -8
- package/dist/packages/@ember/canary-features/index.js +2 -4
- package/dist/packages/@ember/component/index.js +1 -1
- package/dist/packages/@ember/deprecated-features/index.js +0 -1
- package/dist/packages/@ember/destroyable/index.js +15 -4
- package/dist/packages/@ember/engine/index.js +1 -2
- package/dist/packages/@ember/routing/index.js +1 -1
- package/dist/packages/@glimmer/tracking/index.js +203 -1
- package/dist/packages/ember/index.js +9 -61
- package/dist/packages/ember/version.js +1 -1
- package/docs/data.json +430 -1382
- package/lib/index.js +3 -29
- package/package.json +17 -17
- package/dist/packages/@ember/-internals/views/lib/mixins/text_support.js +0 -345
- package/dist/packages/@ember/component/checkbox.js +0 -17
- package/dist/packages/@ember/component/text-area.js +0 -17
- package/dist/packages/@ember/component/text-field.js +0 -17
- package/dist/packages/@ember/routing/link-component.js +0 -17
|
@@ -3,14 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { context } from '@ember/-internals/environment';
|
|
5
5
|
import { get, Mixin, computed } from '@ember/-internals/metal';
|
|
6
|
-
import { assert
|
|
6
|
+
import { assert } from '@ember/debug';
|
|
7
7
|
import { DEBUG } from '@glimmer/env';
|
|
8
|
-
|
|
9
|
-
if (DEBUG && true
|
|
10
|
-
/* EMBER_MODERNIZED_BUILT_IN_COMPONENTS */
|
|
11
|
-
) {
|
|
12
|
-
Mixin._disableDebugSeal = true;
|
|
13
|
-
}
|
|
14
8
|
/**
|
|
15
9
|
`Ember.TargetActionSupport` is a mixin that can be included in a class
|
|
16
10
|
to add a `triggerAction` method with semantics similar to the Handlebars
|
|
@@ -24,7 +18,6 @@ doing more complex event handling in Components.
|
|
|
24
18
|
@private
|
|
25
19
|
*/
|
|
26
20
|
|
|
27
|
-
|
|
28
21
|
const TargetActionSupport = Mixin.create({
|
|
29
22
|
target: null,
|
|
30
23
|
action: null,
|
|
@@ -151,41 +144,8 @@ function getTarget(instance) {
|
|
|
151
144
|
return null;
|
|
152
145
|
}
|
|
153
146
|
|
|
154
|
-
if (
|
|
155
|
-
|
|
156
|
-
) {
|
|
157
|
-
Object.defineProperty(TargetActionSupport, '_wasReopened', {
|
|
158
|
-
configurable: true,
|
|
159
|
-
enumerable: false,
|
|
160
|
-
writable: true,
|
|
161
|
-
value: false
|
|
162
|
-
});
|
|
163
|
-
Object.defineProperty(TargetActionSupport, 'reopen', {
|
|
164
|
-
configurable: true,
|
|
165
|
-
enumerable: false,
|
|
166
|
-
writable: true,
|
|
167
|
-
value: function reopen(...args) {
|
|
168
|
-
if (this === TargetActionSupport) {
|
|
169
|
-
deprecate('Reopening Ember.TargetActionSupport is deprecated.', false, {
|
|
170
|
-
id: 'ember.built-in-components.reopen',
|
|
171
|
-
for: 'ember-source',
|
|
172
|
-
since: {
|
|
173
|
-
enabled: '3.27.0'
|
|
174
|
-
},
|
|
175
|
-
until: '4.0.0',
|
|
176
|
-
url: 'https://deprecations.emberjs.com/v3.x#toc_ember-built-in-components-reopen'
|
|
177
|
-
});
|
|
178
|
-
TargetActionSupport._wasReopened = true;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
return Mixin.prototype.reopen.call(this, ...args);
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
if (DEBUG) {
|
|
186
|
-
Object.seal(TargetActionSupport);
|
|
187
|
-
Mixin._disableDebugSeal = false;
|
|
188
|
-
}
|
|
147
|
+
if (DEBUG) {
|
|
148
|
+
Object.seal(TargetActionSupport);
|
|
189
149
|
}
|
|
190
150
|
|
|
191
151
|
export default TargetActionSupport;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
@module @ember/array
|
|
3
3
|
*/
|
|
4
|
-
import { get, objectAt, alias, PROPERTY_DID_CHANGE, addArrayObserver, removeArrayObserver, replace, arrayContentDidChange, tagForProperty } from '@ember/-internals/metal';
|
|
4
|
+
import { get, objectAt, alias, PROPERTY_DID_CHANGE, addArrayObserver, removeArrayObserver, replace, arrayContentDidChange, arrayContentWillChange, tagForProperty } from '@ember/-internals/metal';
|
|
5
5
|
import { isObject } from '@ember/-internals/utils';
|
|
6
6
|
import EmberObject from './object';
|
|
7
7
|
import { isArray, MutableArray } from '../mixins/array';
|
|
@@ -237,11 +237,11 @@ export default class ArrayProxy extends EmberObject {
|
|
|
237
237
|
|
|
238
238
|
this._removeArrangedContentArrayObserver();
|
|
239
239
|
|
|
240
|
-
|
|
240
|
+
arrayContentWillChange(this, 0, oldLength, newLength);
|
|
241
241
|
|
|
242
242
|
this._invalidate();
|
|
243
243
|
|
|
244
|
-
|
|
244
|
+
arrayContentDidChange(this, 0, oldLength, newLength, false);
|
|
245
245
|
|
|
246
246
|
this._addArrangedContentArrayObserver(arrangedContent);
|
|
247
247
|
}
|
|
@@ -250,21 +250,21 @@ export default class ArrayProxy extends EmberObject {
|
|
|
250
250
|
if (arrangedContent && !arrangedContent.isDestroyed) {
|
|
251
251
|
assert("Can't set ArrayProxy's content to itself", arrangedContent !== this);
|
|
252
252
|
assert(`ArrayProxy expects an Array or ArrayProxy, but you passed ${typeof arrangedContent}`, isArray(arrangedContent) || arrangedContent.isDestroyed);
|
|
253
|
-
addArrayObserver(arrangedContent, this, ARRAY_OBSERVER_MAPPING
|
|
253
|
+
addArrayObserver(arrangedContent, this, ARRAY_OBSERVER_MAPPING);
|
|
254
254
|
this._arrangedContent = arrangedContent;
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
_removeArrangedContentArrayObserver() {
|
|
259
259
|
if (this._arrangedContent) {
|
|
260
|
-
removeArrayObserver(this._arrangedContent, this, ARRAY_OBSERVER_MAPPING
|
|
260
|
+
removeArrayObserver(this._arrangedContent, this, ARRAY_OBSERVER_MAPPING);
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
_arrangedContentArrayWillChange() {}
|
|
265
265
|
|
|
266
266
|
_arrangedContentArrayDidChange(proxy, idx, removedCnt, addedCnt) {
|
|
267
|
-
|
|
267
|
+
arrayContentWillChange(this, idx, removedCnt, addedCnt);
|
|
268
268
|
let dirtyIndex = idx;
|
|
269
269
|
|
|
270
270
|
if (dirtyIndex < 0) {
|
|
@@ -277,7 +277,7 @@ export default class ArrayProxy extends EmberObject {
|
|
|
277
277
|
}
|
|
278
278
|
|
|
279
279
|
this._lengthDirty = true;
|
|
280
|
-
|
|
280
|
+
arrayContentDidChange(this, idx, removedCnt, addedCnt, false);
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
_invalidate() {
|
|
@@ -324,12 +324,5 @@ ArrayProxy.reopen(MutableArray, {
|
|
|
324
324
|
@property arrangedContent
|
|
325
325
|
@public
|
|
326
326
|
*/
|
|
327
|
-
arrangedContent: alias('content')
|
|
328
|
-
|
|
329
|
-
// Array proxies don't need to notify when they change since their `[]` tag is
|
|
330
|
-
// already dependent on the `[]` tag of `arrangedContent`
|
|
331
|
-
arrayContentDidChange(startIdx, removeAmt, addAmt) {
|
|
332
|
-
return arrayContentDidChange(this, startIdx, removeAmt, addAmt, false);
|
|
333
|
-
}
|
|
334
|
-
|
|
327
|
+
arrangedContent: alias('content')
|
|
335
328
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { addChildView, isSimpleClick, getViewBounds, getViewClientRects, getViewBoundingClientRect, getRootViews, getChildViews, getViewId, getElementView, getViewElement, setElementView, setViewElement, clearElementView, clearViewElement, constructStyleDeprecationMessage } from './lib/system/utils';
|
|
2
2
|
export { default as EventDispatcher } from './lib/system/event_dispatcher';
|
|
3
3
|
export { default as ComponentLookup } from './lib/component_lookup';
|
|
4
|
-
export { default as TextSupport } from './lib/mixins/text_support';
|
|
5
4
|
export { default as CoreView } from './lib/views/core_view';
|
|
6
5
|
export { default as ClassNamesSupport } from './lib/mixins/class_names_support';
|
|
7
6
|
export { default as ChildViewsSupport } from './lib/mixins/child_views_support';
|
|
@@ -146,7 +146,7 @@ let mixin = {
|
|
|
146
146
|
the target element you are providing is associated with an `Application`
|
|
147
147
|
and does not have an ancestor element that is associated with an Ember view.
|
|
148
148
|
@method appendTo
|
|
149
|
-
@param {String|DOMElement
|
|
149
|
+
@param {String|DOMElement} A selector, element, HTML string
|
|
150
150
|
@return {Ember.View} receiver
|
|
151
151
|
@private
|
|
152
152
|
*/
|
|
@@ -172,8 +172,8 @@ let mixin = {
|
|
|
172
172
|
})());
|
|
173
173
|
} else {
|
|
174
174
|
target = selector;
|
|
175
|
-
assert(`You tried to append to a selector string (${selector}) in an environment without
|
|
176
|
-
assert(`You tried to append to a non-Element (${selector}) in an environment without
|
|
175
|
+
assert(`You tried to append to a selector string (${selector}) in an environment without a DOM`, typeof target !== 'string');
|
|
176
|
+
assert(`You tried to append to a non-Element (${selector}) in an environment without a DOM`, typeof selector.appendChild === 'function');
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
this.renderer.appendTo(this, target);
|
|
@@ -303,7 +303,7 @@ let mixin = {
|
|
|
303
303
|
Component properties that depend on the presence of an outer element, such
|
|
304
304
|
as `classNameBindings` and `attributeBindings`, do not work with tagless
|
|
305
305
|
components. Tagless components cannot implement methods to handle events,
|
|
306
|
-
and
|
|
306
|
+
and their `element` property has a `null` value.
|
|
307
307
|
@property tagName
|
|
308
308
|
@type String
|
|
309
309
|
@default null
|
|
@@ -110,7 +110,7 @@ import { RouterService } from '@ember/-internals/routing';
|
|
|
110
110
|
});
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
The `rootElement` can be either a DOM element or a
|
|
113
|
+
The `rootElement` can be either a DOM element or a CSS selector
|
|
114
114
|
string. Note that *views appended to the DOM outside the root element will
|
|
115
115
|
not receive events.* If you specify a custom root element, make sure you only
|
|
116
116
|
append views inside it!
|
|
@@ -174,8 +174,7 @@ import { RouterService } from '@ember/-internals/routing';
|
|
|
174
174
|
const Application = Engine.extend({
|
|
175
175
|
/**
|
|
176
176
|
The root DOM element of the Application. This can be specified as an
|
|
177
|
-
element or a
|
|
178
|
-
[jQuery-compatible selector string](http://api.jquery.com/category/selectors/).
|
|
177
|
+
element or a [selector string](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors#reference_table_of_selectors).
|
|
179
178
|
This is the element that will be passed to the Application's,
|
|
180
179
|
`eventDispatcher`, which sets up the listeners for event delegation. Every
|
|
181
180
|
view in your application should be a child of the element you specify here.
|
|
@@ -481,10 +480,10 @@ const Application = Engine.extend({
|
|
|
481
480
|
import Application from '@ember/application';
|
|
482
481
|
let App = Application.create();
|
|
483
482
|
App.deferReadiness();
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
App.token = token;
|
|
483
|
+
fetch('/auth-token')
|
|
484
|
+
.then(response => response.json())
|
|
485
|
+
.then(data => {
|
|
486
|
+
App.token = data.token;
|
|
488
487
|
App.advanceReadiness();
|
|
489
488
|
});
|
|
490
489
|
```
|
|
@@ -831,7 +830,7 @@ const Application = Engine.extend({
|
|
|
831
830
|
in the non-browser environment, the stand-in `document` object only needs to
|
|
832
831
|
implement a limited subset of the full DOM API. The `SimpleDOM` library is known
|
|
833
832
|
to work.
|
|
834
|
-
Since there is no access
|
|
833
|
+
Since there is no DOM access in the non-browser environment, you must also
|
|
835
834
|
specify a DOM `Element` object in the same `document` for the `rootElement` option
|
|
836
835
|
(as opposed to a selector string like `"body"`).
|
|
837
836
|
See the documentation on the `isBrowser`, `document` and `rootElement` properties
|
|
@@ -16,11 +16,10 @@ export const DEFAULT_FEATURES = {
|
|
|
16
16
|
EMBER_NAMED_BLOCKS: true,
|
|
17
17
|
EMBER_GLIMMER_HELPER_MANAGER: true,
|
|
18
18
|
EMBER_GLIMMER_INVOKE_HELPER: true,
|
|
19
|
-
EMBER_MODERNIZED_BUILT_IN_COMPONENTS: true,
|
|
20
19
|
EMBER_STRICT_MODE: true,
|
|
21
20
|
EMBER_DYNAMIC_HELPERS_AND_MODIFIERS: true,
|
|
22
|
-
EMBER_ROUTING_ROUTER_SERVICE_REFRESH:
|
|
23
|
-
EMBER_CACHED:
|
|
21
|
+
EMBER_ROUTING_ROUTER_SERVICE_REFRESH: true,
|
|
22
|
+
EMBER_CACHED: true
|
|
24
23
|
};
|
|
25
24
|
/**
|
|
26
25
|
The hash of enabled Canary features. Add to this, any canary features
|
|
@@ -74,7 +73,6 @@ export const EMBER_IMPROVED_INSTRUMENTATION = featureValue(FEATURES.EMBER_IMPROV
|
|
|
74
73
|
export const EMBER_NAMED_BLOCKS = featureValue(FEATURES.EMBER_NAMED_BLOCKS);
|
|
75
74
|
export const EMBER_GLIMMER_HELPER_MANAGER = featureValue(FEATURES.EMBER_GLIMMER_HELPER_MANAGER);
|
|
76
75
|
export const EMBER_GLIMMER_INVOKE_HELPER = featureValue(FEATURES.EMBER_GLIMMER_INVOKE_HELPER);
|
|
77
|
-
export const EMBER_MODERNIZED_BUILT_IN_COMPONENTS = featureValue(FEATURES.EMBER_MODERNIZED_BUILT_IN_COMPONENTS);
|
|
78
76
|
export const EMBER_STRICT_MODE = featureValue(FEATURES.EMBER_STRICT_MODE);
|
|
79
77
|
export const EMBER_DYNAMIC_HELPERS_AND_MODIFIERS = featureValue(FEATURES.EMBER_DYNAMIC_HELPERS_AND_MODIFIERS);
|
|
80
78
|
export const EMBER_ROUTING_ROUTER_SERVICE_REFRESH = featureValue(FEATURES.EMBER_ROUTING_ROUTER_SERVICE_REFRESH);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { setComponentTemplate, getComponentTemplate } from '@glimmer/manager';
|
|
2
|
-
export { Component as default, Input } from '@ember/-internals/glimmer';
|
|
2
|
+
export { Component as default, Input, Textarea } from '@ember/-internals/glimmer';
|
|
3
3
|
export { componentCapabilities as capabilities, setComponentManager } from '@ember/-internals/glimmer';
|
|
@@ -22,7 +22,9 @@ import { registerDestructor as _registerDestructor, unregisterDestructor as _unr
|
|
|
22
22
|
|
|
23
23
|
```js
|
|
24
24
|
class CustomSelect extends Component {
|
|
25
|
-
constructor() {
|
|
25
|
+
constructor(...args) {
|
|
26
|
+
super(...args);
|
|
27
|
+
|
|
26
28
|
// obj is now a child of the component. When the component is destroyed,
|
|
27
29
|
// obj will also be destroyed, and have all of its destructors triggered.
|
|
28
30
|
this.obj = associateDestroyableChild(this, {});
|
|
@@ -153,12 +155,15 @@ import { registerDestructor as _registerDestructor, unregisterDestructor as _unr
|
|
|
153
155
|
parent is destroyed, the destructor function will be called.
|
|
154
156
|
|
|
155
157
|
```js
|
|
158
|
+
import Component from '@glimmer/component';
|
|
156
159
|
import { registerDestructor } from '@ember/destroyable';
|
|
157
160
|
|
|
158
161
|
class Modal extends Component {
|
|
159
162
|
@service resize;
|
|
160
163
|
|
|
161
|
-
constructor() {
|
|
164
|
+
constructor(...args) {
|
|
165
|
+
super(...args);
|
|
166
|
+
|
|
162
167
|
this.resize.register(this, this.layout);
|
|
163
168
|
|
|
164
169
|
registerDestructor(this, () => this.resize.unregister(this));
|
|
@@ -175,6 +180,7 @@ import { registerDestructor as _registerDestructor, unregisterDestructor as _unr
|
|
|
175
180
|
than creating a closure function per destroyable.
|
|
176
181
|
|
|
177
182
|
```js
|
|
183
|
+
import Component from '@glimmer/component';
|
|
178
184
|
import { registerDestructor } from '@ember/destroyable';
|
|
179
185
|
|
|
180
186
|
function unregisterResize(instance) {
|
|
@@ -184,7 +190,9 @@ import { registerDestructor as _registerDestructor, unregisterDestructor as _unr
|
|
|
184
190
|
class Modal extends Component {
|
|
185
191
|
@service resize;
|
|
186
192
|
|
|
187
|
-
constructor() {
|
|
193
|
+
constructor(...args) {
|
|
194
|
+
super(...args);
|
|
195
|
+
|
|
188
196
|
this.resize.register(this, this.layout);
|
|
189
197
|
|
|
190
198
|
registerDestructor(this, unregisterResize);
|
|
@@ -208,12 +216,15 @@ export function registerDestructor(destroyable, destructor) {
|
|
|
208
216
|
from the destroyable.
|
|
209
217
|
|
|
210
218
|
```js
|
|
219
|
+
import Component from '@glimmer/component';
|
|
211
220
|
import { registerDestructor, unregisterDestructor } from '@ember/destroyable';
|
|
212
221
|
|
|
213
222
|
class Modal extends Component {
|
|
214
223
|
@service modals;
|
|
215
224
|
|
|
216
|
-
constructor() {
|
|
225
|
+
constructor(...args) {
|
|
226
|
+
super(...args);
|
|
227
|
+
|
|
217
228
|
this.modals.add(this);
|
|
218
229
|
|
|
219
230
|
this.modalDestructor = registerDestructor(this, () => this.modals.remove(this));
|
|
@@ -292,7 +292,6 @@ Engine.reopenClass({
|
|
|
292
292
|
and after.
|
|
293
293
|
Example instanceInitializer to preload data into the store.
|
|
294
294
|
```app/initializer/preload-data.js
|
|
295
|
-
import $ from 'jquery';
|
|
296
295
|
export function initialize(application) {
|
|
297
296
|
var userConfig, userConfigEncoded, store;
|
|
298
297
|
// We have a HTML escaped JSON representation of the user's basic
|
|
@@ -303,7 +302,7 @@ Engine.reopenClass({
|
|
|
303
302
|
// like all local models and data can be manipulated by the user, so it
|
|
304
303
|
// should not be relied upon for security or authorization.
|
|
305
304
|
// Grab the encoded data from the meta tag
|
|
306
|
-
userConfigEncoded =
|
|
305
|
+
userConfigEncoded = document.querySelector('head meta[name=app-user-config]').attr('content');
|
|
307
306
|
// Unescape the text, then parse the resulting JSON into a real object
|
|
308
307
|
userConfig = JSON.parse(unescape(userConfigEncoded));
|
|
309
308
|
// Lookup the store
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { LinkTo } from '@ember/-internals/glimmer';
|
|
@@ -1 +1,203 @@
|
|
|
1
|
-
export { tracked, cached } from '@ember/-internals/metal';
|
|
1
|
+
export { tracked, cached } from '@ember/-internals/metal';
|
|
2
|
+
/**
|
|
3
|
+
In order to tell Ember a value might change, we need to mark it as trackable.
|
|
4
|
+
Trackable values are values that:
|
|
5
|
+
|
|
6
|
+
- Can change over their component’s lifetime and
|
|
7
|
+
- Should cause Ember to rerender if and when they change
|
|
8
|
+
|
|
9
|
+
We can do this by marking the field with the `@tracked` decorator.
|
|
10
|
+
|
|
11
|
+
@module @glimmer/tracking
|
|
12
|
+
@public
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
Marks a property as tracked. By default, values that are rendered in Ember app
|
|
17
|
+
templates are _static_, meaning that updates to them won't cause the
|
|
18
|
+
application to rerender. Marking a property as tracked means that when that
|
|
19
|
+
property changes, any templates that used that property, directly or
|
|
20
|
+
indirectly, will rerender. For instance, consider this component:
|
|
21
|
+
|
|
22
|
+
```handlebars
|
|
23
|
+
<div>Count: {{this.count}}</div>
|
|
24
|
+
<div>Times Ten: {{this.timesTen}}</div>
|
|
25
|
+
<div>
|
|
26
|
+
<button {{on "click" this.plusOne}}>
|
|
27
|
+
Plus One
|
|
28
|
+
</button>
|
|
29
|
+
</div>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
import Component from '@glimmer/component';
|
|
34
|
+
import { tracked } from '@glimmer/tracking';
|
|
35
|
+
import { action } from '@ember/object';
|
|
36
|
+
|
|
37
|
+
export default class CounterComponent extends Component {
|
|
38
|
+
@tracked count = 0;
|
|
39
|
+
|
|
40
|
+
get timesTen() {
|
|
41
|
+
return this.count * 10;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@action
|
|
45
|
+
plusOne() {
|
|
46
|
+
this.count += 1;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Both the `{{this.count}}` and the `{{this.timesTen}}` properties in the
|
|
52
|
+
template will update whenever the button is clicked. Any tracked properties
|
|
53
|
+
that are used in any way to calculate a value that is used in the template
|
|
54
|
+
will cause a rerender when updated - this includes through method calls and
|
|
55
|
+
other means:
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
import Component from '@glimmer/component';
|
|
59
|
+
import { tracked } from '@glimmer/tracking';
|
|
60
|
+
|
|
61
|
+
class Entry {
|
|
62
|
+
@tracked name;
|
|
63
|
+
@tracked phoneNumber;
|
|
64
|
+
|
|
65
|
+
constructor(name, phoneNumber) {
|
|
66
|
+
this.name = name;
|
|
67
|
+
this.phoneNumber = phoneNumber;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export default class PhoneBookComponent extends Component {
|
|
72
|
+
entries = [
|
|
73
|
+
new Entry('Pizza Palace', 5551234),
|
|
74
|
+
new Entry('1st Street Cleaners', 5554321),
|
|
75
|
+
new Entry('Plants R Us', 5552468),
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
// Any usage of this property will update whenever any of the names in the
|
|
79
|
+
// entries arrays are updated
|
|
80
|
+
get names() {
|
|
81
|
+
return this.entries.map(e => e.name);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Any usage of this property will update whenever any of the numbers in the
|
|
85
|
+
// entries arrays are updated
|
|
86
|
+
get numbers() {
|
|
87
|
+
return this.getFormattedNumbers();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
getFormattedNumbers() {
|
|
91
|
+
return this.entries
|
|
92
|
+
.map(e => e.phoneNumber)
|
|
93
|
+
.map(number => {
|
|
94
|
+
let numberString = '' + number;
|
|
95
|
+
|
|
96
|
+
return numberString.slice(0, 3) + '-' + numberString.slice(3);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
It's important to note that setting tracked properties will always trigger an
|
|
103
|
+
update, even if the property is set to the same value as it was before.
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
let entry = new Entry('Pizza Palace', 5551234);
|
|
107
|
+
// if entry was used when rendering, this would cause a rerender, even though
|
|
108
|
+
// the name is being set to the same value as it was before
|
|
109
|
+
entry.name = entry.name;
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`tracked` can also be used with the classic Ember object model in a similar
|
|
113
|
+
manner to classic computed properties:
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
import EmberObject from '@ember/object';
|
|
117
|
+
import { tracked } from '@glimmer/tracking';
|
|
118
|
+
|
|
119
|
+
const Entry = EmberObject.extend({
|
|
120
|
+
name: tracked(),
|
|
121
|
+
phoneNumber: tracked()
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Often this is unnecessary, but to ensure robust auto-tracking behavior it is
|
|
126
|
+
advisable to mark tracked state appropriately wherever possible.
|
|
127
|
+
This form of `tracked` also accepts an optional configuration object
|
|
128
|
+
containing either an initial `value` or an `initializer` function (but not
|
|
129
|
+
both).
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
import EmberObject from '@ember/object';
|
|
133
|
+
import { tracked } from '@glimmer/tracking';
|
|
134
|
+
|
|
135
|
+
const Entry = EmberObject.extend({
|
|
136
|
+
name: tracked({ value: 'Zoey' }),
|
|
137
|
+
favoriteSongs: tracked({
|
|
138
|
+
initializer: () => ['Raspberry Beret', 'Time After Time']
|
|
139
|
+
})
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
@method tracked
|
|
144
|
+
@static
|
|
145
|
+
@for @glimmer/tracking
|
|
146
|
+
@public
|
|
147
|
+
*/
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
The `@cached` decorator can be used on getters in order to cache the return
|
|
151
|
+
value of the getter. This is useful when a getter is expensive and used very
|
|
152
|
+
often. For instance, in this guest list class, we have the `sortedGuests`
|
|
153
|
+
getter that sorts the guests alphabetically:
|
|
154
|
+
|
|
155
|
+
```js
|
|
156
|
+
import { tracked } from '@glimmer/tracking';
|
|
157
|
+
|
|
158
|
+
class GuestList {
|
|
159
|
+
@tracked guests = ['Zoey', 'Tomster'];
|
|
160
|
+
|
|
161
|
+
get sortedGuests() {
|
|
162
|
+
return this.guests.slice().sort()
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Every time `sortedGuests` is accessed, a new array will be created and sorted,
|
|
168
|
+
because JavaScript getters do not cache by default. When the guest list is
|
|
169
|
+
small, like the one in the example, this is not a problem. However, if the guest
|
|
170
|
+
list were to grow very large, it would mean that we would be doing a large
|
|
171
|
+
amount of work each time we accessed `sortedGetters`. With `@cached`, we can
|
|
172
|
+
cache the value instead:
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
import { tracked, cached } from '@glimmer/tracking';
|
|
176
|
+
|
|
177
|
+
class GuestList {
|
|
178
|
+
@tracked guests = ['Zoey', 'Tomster'];
|
|
179
|
+
|
|
180
|
+
@cached
|
|
181
|
+
get sortedGuests() {
|
|
182
|
+
return this.guests.slice().sort()
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Now the `sortedGuests` getter will be cached based on _autotracking_. It will
|
|
188
|
+
only rerun and create a new sorted array when the `guests` tracked property is
|
|
189
|
+
updated.
|
|
190
|
+
|
|
191
|
+
In general, you should avoid using `@cached` unless you have confirmed that the
|
|
192
|
+
getter you are decorating is computationally expensive. `@cached` adds a small
|
|
193
|
+
amount of overhead to the getter, making it more expensive. While this overhead
|
|
194
|
+
is small, if `@cached` is overused it can add up to a large impact overall in
|
|
195
|
+
your app. Many getters and tracked properties are only accessed once, rendered,
|
|
196
|
+
and then never rerendered, so adding `@cached` when it is unnecessary can
|
|
197
|
+
negatively impact performance.
|
|
198
|
+
|
|
199
|
+
@method cached
|
|
200
|
+
@static
|
|
201
|
+
@for @glimmer/tracking
|
|
202
|
+
@public
|
|
203
|
+
*/
|
|
@@ -15,8 +15,8 @@ import { _getStrings, _setStrings, dasherize, camelize, capitalize, classify, de
|
|
|
15
15
|
import Service, { service } from '@ember/service';
|
|
16
16
|
import { action, computed } from '@ember/object';
|
|
17
17
|
import { dependentKeyCompat } from '@ember/object/compat';
|
|
18
|
-
import { Object as EmberObject, RegistryProxyMixin, ContainerProxyMixin, compare, isEqual, Array as EmberArray, MutableEnumerable, MutableArray,
|
|
19
|
-
import {
|
|
18
|
+
import { Object as EmberObject, RegistryProxyMixin, ContainerProxyMixin, compare, isEqual, Array as EmberArray, MutableEnumerable, MutableArray, Evented, PromiseProxyMixin, Observable, typeOf, isArray, _ProxyMixin, RSVP, Comparable, Namespace, Enumerable, ArrayProxy, ObjectProxy, ActionHandler, CoreObject, NativeArray, A } from '@ember/-internals/runtime';
|
|
19
|
+
import { Component, componentCapabilities, modifierCapabilities, setComponentManager, escapeExpression, getTemplates, Helper, helper, htmlSafe, isHTMLSafe, setTemplates, template, Input, isSerializationFirstNode } from '@ember/-internals/glimmer'; // eslint-disable-next-line import/no-unresolved
|
|
20
20
|
|
|
21
21
|
import VERSION from './version';
|
|
22
22
|
import * as views from '@ember/-internals/views';
|
|
@@ -164,12 +164,16 @@ Ember._isDestroyed = isDestroyed;
|
|
|
164
164
|
and reporting code.
|
|
165
165
|
|
|
166
166
|
```javascript
|
|
167
|
-
import $ from 'jquery';
|
|
168
167
|
|
|
169
168
|
Ember.onerror = function(error) {
|
|
170
|
-
|
|
169
|
+
const payload = {
|
|
171
170
|
stack: error.stack,
|
|
172
171
|
otherInformation: 'whatever app state you want to provide'
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
fetch('/report-error', {
|
|
175
|
+
method: 'POST',
|
|
176
|
+
body: JSON.stringify(payload)
|
|
173
177
|
});
|
|
174
178
|
};
|
|
175
179
|
```
|
|
@@ -296,52 +300,6 @@ Object.defineProperty(Ember, 'BOOTED', {
|
|
|
296
300
|
Ember.Component = Component;
|
|
297
301
|
Helper.helper = helper;
|
|
298
302
|
Ember.Helper = Helper;
|
|
299
|
-
|
|
300
|
-
if (true
|
|
301
|
-
/* EMBER_MODERNIZED_BUILT_IN_COMPONENTS */
|
|
302
|
-
) {
|
|
303
|
-
[['Checkbox', '@ember/component/checkbox', Checkbox, true], ['TextField', '@ember/component/text-field', TextField, true], ['TextArea', '@ember/component/text-area', TextArea, true], ['LinkComponent', '@ember/routing/link-component', LinkComponent, true], ['TextSupport', null, views.TextSupport, false], ['TargetActionSupport', null, TargetActionSupport, false]].forEach(([name, path, value, availableInLegacyAddon]) => {
|
|
304
|
-
Object.defineProperty(Ember, name, {
|
|
305
|
-
get() {
|
|
306
|
-
let message = `Using Ember.${name}`;
|
|
307
|
-
|
|
308
|
-
if (path !== null) {
|
|
309
|
-
message += ` or importing from '${path}'`;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
message += ` is deprecated.`;
|
|
313
|
-
|
|
314
|
-
if (availableInLegacyAddon) {
|
|
315
|
-
message += ` Install the \`@ember/legacy-built-in-components\` addon and use ` + `\`import { ${name} } from '@ember/legacy-built-in-components';\` instead.`;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
deprecate(message, false, {
|
|
319
|
-
id: 'ember.built-in-components.import',
|
|
320
|
-
until: '4.0.0',
|
|
321
|
-
for: 'ember-source',
|
|
322
|
-
since: {
|
|
323
|
-
enabled: '3.27.0'
|
|
324
|
-
},
|
|
325
|
-
url: 'https://deprecations.emberjs.com/v3.x#toc_ember-built-in-components-import'
|
|
326
|
-
});
|
|
327
|
-
return value;
|
|
328
|
-
},
|
|
329
|
-
|
|
330
|
-
configurable: true,
|
|
331
|
-
enumerable: true
|
|
332
|
-
}); // Expose a non-deprecated version for tests and the @ember/legacy-built-in-components addon
|
|
333
|
-
|
|
334
|
-
Ember[`_Legacy${name}`] = value;
|
|
335
|
-
});
|
|
336
|
-
} else {
|
|
337
|
-
Ember.Checkbox = Checkbox;
|
|
338
|
-
Ember.TextField = TextField;
|
|
339
|
-
Ember.TextArea = TextArea;
|
|
340
|
-
Ember.LinkComponent = LinkComponent;
|
|
341
|
-
Ember.TextSupport = views.TextSupport;
|
|
342
|
-
Ember.TargetActionSupport = TargetActionSupport;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
303
|
Ember._setComponentManager = setComponentManager;
|
|
346
304
|
Ember._componentManagerCapabilities = componentCapabilities;
|
|
347
305
|
Ember._setModifierManager = setModifierManager;
|
|
@@ -553,14 +511,4 @@ Ember.__loader = {
|
|
|
553
511
|
// eslint-disable-next-line no-undef
|
|
554
512
|
registry: typeof requirejs !== 'undefined' ? requirejs.entries : require.entries
|
|
555
513
|
};
|
|
556
|
-
export default Ember;
|
|
557
|
-
/**
|
|
558
|
-
@module jquery
|
|
559
|
-
@public
|
|
560
|
-
*/
|
|
561
|
-
|
|
562
|
-
/**
|
|
563
|
-
@class jquery
|
|
564
|
-
@public
|
|
565
|
-
@static
|
|
566
|
-
*/
|
|
514
|
+
export default Ember;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export default "4.
|
|
1
|
+
export default "4.2.0-alpha.1";
|