Skip to content

Commit 61b6e00

Browse files
committed
Remove observer methods from EmberObject - No more public observers!
1 parent ed846b5 commit 61b6e00

File tree

7 files changed

+3
-386
lines changed

7 files changed

+3
-386
lines changed

packages/@ember/-internals/glimmer/tests/integration/helpers/unbound-test.js

Lines changed: 2 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
1-
import {
2-
RenderingTestCase,
3-
moduleFor,
4-
strip,
5-
runTask,
6-
runLoopSettled,
7-
} from 'internal-test-helpers';
1+
import { RenderingTestCase, moduleFor, strip, runTask } from 'internal-test-helpers';
82

9-
import { set, get, setProperties } from '@ember/object';
3+
import { set, setProperties } from '@ember/object';
104

115
import { Component } from '../../utils/helpers';
126

@@ -368,76 +362,6 @@ moduleFor(
368362
this.assertText('abc abc');
369363
}
370364

371-
async ['@test should be able to render an unbound helper invocation for helpers with dependent keys']() {
372-
this.registerHelper('capitalizeName', {
373-
destroy() {
374-
this.removeObserver('value.firstName', this, this.recompute);
375-
this._super(...arguments);
376-
},
377-
378-
compute([value]) {
379-
if (this.value) {
380-
this.removeObserver('value.firstName', this, this.recompute);
381-
}
382-
set(this, 'value', value);
383-
this.addObserver('value.firstName', this, this.recompute);
384-
return value ? get(value, 'firstName').toUpperCase() : '';
385-
},
386-
});
387-
388-
this.registerHelper('concatNames', {
389-
destroy() {
390-
this.teardown();
391-
this._super(...arguments);
392-
},
393-
teardown() {
394-
this.removeObserver('value.firstName', this, this.recompute);
395-
this.removeObserver('value.lastName', this, this.recompute);
396-
},
397-
compute([value]) {
398-
if (this.value) {
399-
this.teardown();
400-
}
401-
set(this, 'value', value);
402-
this.addObserver('value.firstName', this, this.recompute);
403-
this.addObserver('value.lastName', this, this.recompute);
404-
return (value ? get(value, 'firstName') : '') + (value ? get(value, 'lastName') : '');
405-
},
406-
});
407-
408-
this.render(
409-
`{{capitalizeName this.person}} {{unbound (capitalizeName this.person)}} {{concatNames this.person}} {{unbound (concatNames this.person)}}`,
410-
{
411-
person: {
412-
firstName: 'shooby',
413-
lastName: 'taylor',
414-
},
415-
}
416-
);
417-
418-
this.assertText('SHOOBY SHOOBY shoobytaylor shoobytaylor');
419-
420-
runTask(() => this.rerender());
421-
await runLoopSettled();
422-
423-
this.assertText('SHOOBY SHOOBY shoobytaylor shoobytaylor');
424-
425-
runTask(() => set(this.context, 'person.firstName', 'sally'));
426-
await runLoopSettled();
427-
428-
this.assertText('SALLY SHOOBY sallytaylor shoobytaylor');
429-
430-
runTask(() =>
431-
set(this.context, 'person', {
432-
firstName: 'shooby',
433-
lastName: 'taylor',
434-
})
435-
);
436-
await runLoopSettled();
437-
438-
this.assertText('SHOOBY SHOOBY shoobytaylor shoobytaylor');
439-
}
440-
441365
['@test should be able to render an unbound helper invocation in #each helper']() {
442366
this.registerHelper('capitalize', (params) => params[0].toUpperCase());
443367

@@ -483,76 +407,6 @@ moduleFor(
483407
this.assertText('SHOOBY SHOOBYCINDY CINDY');
484408
}
485409

486-
async ['@test should be able to render an unbound helper invocation with bound hash options']() {
487-
this.registerHelper('capitalizeName', {
488-
destroy() {
489-
this.removeObserver('value.firstName', this, this.recompute);
490-
this._super(...arguments);
491-
},
492-
493-
compute([value]) {
494-
if (this.value) {
495-
this.removeObserver('value.firstName', this, this.recompute);
496-
}
497-
set(this, 'value', value);
498-
this.addObserver('value.firstName', this, this.recompute);
499-
return value ? get(value, 'firstName').toUpperCase() : '';
500-
},
501-
});
502-
503-
this.registerHelper('concatNames', {
504-
destroy() {
505-
this.teardown();
506-
this._super(...arguments);
507-
},
508-
teardown() {
509-
this.removeObserver('value.firstName', this, this.recompute);
510-
this.removeObserver('value.lastName', this, this.recompute);
511-
},
512-
compute([value]) {
513-
if (this.value) {
514-
this.teardown();
515-
}
516-
set(this, 'value', value);
517-
this.addObserver('value.firstName', this, this.recompute);
518-
this.addObserver('value.lastName', this, this.recompute);
519-
return (value ? get(value, 'firstName') : '') + (value ? get(value, 'lastName') : '');
520-
},
521-
});
522-
523-
this.render(
524-
`{{capitalizeName this.person}} {{unbound (capitalizeName this.person)}} {{concatNames this.person}} {{unbound (concatNames this.person)}}`,
525-
{
526-
person: {
527-
firstName: 'shooby',
528-
lastName: 'taylor',
529-
},
530-
}
531-
);
532-
await runLoopSettled();
533-
534-
this.assertText('SHOOBY SHOOBY shoobytaylor shoobytaylor');
535-
536-
runTask(() => this.rerender());
537-
await runLoopSettled();
538-
539-
this.assertText('SHOOBY SHOOBY shoobytaylor shoobytaylor');
540-
541-
runTask(() => set(this.context, 'person.firstName', 'sally'));
542-
await runLoopSettled();
543-
544-
this.assertText('SALLY SHOOBY sallytaylor shoobytaylor');
545-
546-
runTask(() =>
547-
set(this.context, 'person', {
548-
firstName: 'shooby',
549-
lastName: 'taylor',
550-
})
551-
);
552-
553-
this.assertText('SHOOBY SHOOBY shoobytaylor shoobytaylor');
554-
}
555-
556410
['@test should be able to render bound form of a helper inside unbound form of same helper']() {
557411
this.render(
558412
strip`

packages/@ember/controller/tests/controller_test.js

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,33 +37,6 @@ moduleFor(
3737
runTask(() => this.$('button').click());
3838
this.assertText('2');
3939
}
40-
41-
async '@test model can be observed with sync observers'(assert) {
42-
let observerRunCount = 0;
43-
44-
this.add(
45-
'controller:index',
46-
class extends Controller {
47-
constructor() {
48-
super(...arguments);
49-
this.model = 0;
50-
51-
this.addObserver('model', this, () => observerRunCount++, true);
52-
}
53-
54-
@action
55-
update() {
56-
this.model++;
57-
}
58-
}
59-
);
60-
61-
this.addTemplate('index', '<button {{on "click" this.update}}>{{this.model}}</button>');
62-
63-
await this.visit('/');
64-
runTask(() => this.$('button').click());
65-
assert.equal(observerRunCount, 1, 'observer ran exactly once');
66-
}
6740
}
6841
);
6942

packages/@ember/object/index.ts

Lines changed: 1 addition & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
11
import { assert } from '@ember/debug';
22
import type { ElementDescriptor, ExtendedMethodDecorator } from '@ember/-internals/metal';
3-
import {
4-
isElementDescriptor,
5-
setClassicDecorator,
6-
hasListeners,
7-
addObserver,
8-
removeObserver,
9-
get,
10-
set,
11-
} from '@ember/-internals/metal';
3+
import { isElementDescriptor, setClassicDecorator, get, set } from '@ember/-internals/metal';
124
import { getFactoryFor } from '@ember/-internals/container';
135
import CoreObject from '@ember/object/core';
146
import { peekMeta } from '@ember/-internals/meta';
@@ -24,10 +16,6 @@ export {
2416
trySet,
2517
} from '@ember/-internals/metal';
2618

27-
type ObserverMethod<Target, Sender> =
28-
| (keyof Target & string)
29-
| ((this: Target, sender: Sender, key: string, value: any, rev: number) => void);
30-
3119
/**
3220
@module @ember/object
3321
*/
@@ -40,149 +28,6 @@ type ObserverMethod<Target, Sender> =
4028
@public
4129
*/
4230
class EmberObject extends CoreObject {
43-
/**
44-
Adds an observer on a property.
45-
46-
This is the core method used to register an observer for a property.
47-
48-
Once you call this method, any time the key's value is set, your observer
49-
will be notified. Note that the observers are triggered any time the
50-
value is set, regardless of whether it has actually changed. Your
51-
observer should be prepared to handle that.
52-
53-
There are two common invocation patterns for `.addObserver()`:
54-
55-
- Passing two arguments:
56-
- the name of the property to observe (as a string)
57-
- the function to invoke (an actual function)
58-
- Passing three arguments:
59-
- the name of the property to observe (as a string)
60-
- the target object (will be used to look up and invoke a
61-
function on)
62-
- the name of the function to invoke on the target object
63-
(as a string).
64-
65-
```app/components/my-component.js
66-
import Component from '@ember/component';
67-
68-
export default Component.extend({
69-
init() {
70-
this._super(...arguments);
71-
72-
// the following are equivalent:
73-
74-
// using three arguments
75-
this.addObserver('foo', this, 'fooDidChange');
76-
77-
// using two arguments
78-
this.addObserver('foo', (...args) => {
79-
this.fooDidChange(...args);
80-
});
81-
},
82-
83-
fooDidChange() {
84-
// your custom logic code
85-
}
86-
});
87-
```
88-
89-
### Observer Methods
90-
91-
Observer methods have the following signature:
92-
93-
```app/components/my-component.js
94-
import Component from '@ember/component';
95-
96-
export default Component.extend({
97-
init() {
98-
this._super(...arguments);
99-
this.addObserver('foo', this, 'fooDidChange');
100-
},
101-
102-
fooDidChange(sender, key, value, rev) {
103-
// your code
104-
}
105-
});
106-
```
107-
108-
The `sender` is the object that changed. The `key` is the property that
109-
changes. The `value` property is currently reserved and unused. The `rev`
110-
is the last property revision of the object when it changed, which you can
111-
use to detect if the key value has really changed or not.
112-
113-
Usually you will not need the value or revision parameters at
114-
the end. In this case, it is common to write observer methods that take
115-
only a sender and key value as parameters or, if you aren't interested in
116-
any of these values, to write an observer that has no parameters at all.
117-
118-
@method addObserver
119-
@param {String} key The key to observe
120-
@param {Object} target The target object to invoke
121-
@param {String|Function} method The method to invoke
122-
@param {Boolean} sync Whether the observer is sync or not
123-
@return {Observable}
124-
@public
125-
*/
126-
addObserver<Target extends object | Function | null>(
127-
key: keyof this & string,
128-
target: Target,
129-
method: ObserverMethod<Target, this>
130-
): this;
131-
addObserver(key: keyof this & string, method: ObserverMethod<this, this>): this;
132-
addObserver<Target extends object | Function | null>(
133-
key: string,
134-
target: Target,
135-
method?: ObserverMethod<Target, this>,
136-
sync?: boolean
137-
) {
138-
addObserver(this, key, target, method, sync);
139-
return this;
140-
}
141-
142-
/**
143-
Remove an observer you have previously registered on this object. Pass
144-
the same key, target, and method you passed to `addObserver()` and your
145-
target will no longer receive notifications.
146-
147-
@method removeObserver
148-
@param {String} key The key to observe
149-
@param {Object} target The target object to invoke
150-
@param {String|Function} method The method to invoke
151-
@param {Boolean} sync Whether the observer is async or not
152-
@return {Observable}
153-
@public
154-
*/
155-
removeObserver<Target extends object | Function | null>(
156-
key: keyof this & string,
157-
target: Target,
158-
method: ObserverMethod<Target, this>
159-
): this;
160-
removeObserver(key: keyof this & string, method: ObserverMethod<this, this>): this;
161-
removeObserver<Target extends object | Function | null>(
162-
key: string,
163-
target: Target,
164-
method?: string | Function,
165-
sync?: boolean
166-
) {
167-
removeObserver(this, key, target, method, sync);
168-
return this;
169-
}
170-
171-
/**
172-
Returns `true` if the object currently has observers registered for a
173-
particular key. You can use this method to potentially defer performing
174-
an expensive action until someone begins observing a particular property
175-
on the object.
176-
177-
@method hasObserverFor
178-
@param {String} key Key to check
179-
@return {Boolean}
180-
@private
181-
*/
182-
hasObserverFor(key: string) {
183-
return hasListeners(this, `${key}:change`);
184-
}
185-
18631
// NOT TYPE SAFE!
18732
/**
18833
Set the value of a property to the current value plus some amount.

0 commit comments

Comments
 (0)