Skip to content

Commit

Permalink
Merge pull request #13424 from robbiepitts/deprecate-ember-binding
Browse files Browse the repository at this point in the history
[DEPRECATE] Deprecate Ember.Binding
  • Loading branch information
mmun committed May 3, 2016
2 parents 715fb54 + bc8903f commit 3cfc961
Show file tree
Hide file tree
Showing 16 changed files with 339 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,17 @@ moduleFor('Binding integration tests', class extends RenderingTest {
template: 'two way: {{twoWayTest}}, string: {{stringTest}}, object: {{twoWayObjectTest}}, string object: {{stringObjectTest}}'
});

this.render('{{foo-bar direction=direction displacement=displacement}}', {
direction: 'down',
displacement: {
distance: 10
}
});
let deprecationMessage = '`Ember.Binding` is deprecated. Consider' +
' using an `alias` computed property instead.';

expectDeprecation(() => {
this.render('{{foo-bar direction=direction displacement=displacement}}', {
direction: 'down',
displacement: {
distance: 10
}
});
}, deprecationMessage);

this.assertText('two way: down, string: down, object: 10, string object: 10');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,10 @@ moduleFor('Helpers test: {{unbound}}', class extends RenderingTest {

this.render(`{{unbound (repeat foo count=bar)}} {{repeat foo count=bar}} {{unbound (repeat foo count=2)}} {{repeat foo count=4}}`, {
foo: 'X',
numRepeatsBinding: 'bar',
bar: 5
});


this.assertText('XXXXX XXXXX XX XXXX');

this.runTask(() => this.rerender());
Expand Down
37 changes: 34 additions & 3 deletions packages/ember-metal/lib/binding.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Logger from 'ember-console';
import { context, ENV } from 'ember-environment';
import run from 'ember-metal/run_loop';
import { assert } from 'ember-metal/debug';
import { assert, deprecate } from 'ember-metal/debug';
import { get } from 'ember-metal/property_get';
import { trySet } from 'ember-metal/property_set';
import { guidFor } from 'ember-metal/utils';
Expand Down Expand Up @@ -43,6 +43,7 @@ function Binding(toPath, fromPath) {
/**
@class Binding
@namespace Ember
@deprecated See http://emberjs.com/deprecations/v2.x#toc_ember-binding
@public
*/

Expand Down Expand Up @@ -144,13 +145,13 @@ Binding.prototype = {
connect(obj) {
assert('Must pass a valid object to Ember.Binding.connect()', !!obj);

let fromObj, fromPath;
let fromObj, fromPath, possibleGlobal;

// If the binding's "from" path could be interpreted as a global, verify
// whether the path refers to a global or not by consulting `Ember.lookup`.
if (isGlobalPath(this._from)) {
let name = getFirstKey(this._from);
let possibleGlobal = context.lookup[name];
possibleGlobal = context.lookup[name];

if (possibleGlobal) {
fromObj = possibleGlobal;
Expand All @@ -175,6 +176,10 @@ Binding.prototype = {

addListener(obj, 'willDestroy', this, 'disconnect');

fireDeprecations(possibleGlobal,
this._oneWay,
(!possibleGlobal && !this._oneWay));

this._readyToSync = true;
this._fromObj = fromObj;
this._fromPath = fromPath;
Expand Down Expand Up @@ -281,6 +286,32 @@ Binding.prototype = {

};

function fireDeprecations(deprecateGlobal, deprecateOneWay, deprecateAlias) {
let deprecateGlobalMessage = '`Ember.Binding` is deprecated. Since you' +
' are binding to a global consider using a service instead.';
let deprecateOneWayMessage = '`Ember.Binding` is deprecated. Since you' +
' are using a `oneWay` binding consider using a `readOnly` computed' +
' property instead.';
let deprecateAliasMessage = '`Ember.Binding` is deprecated. Consider' +
' using an `alias` computed property instead.';

deprecate(deprecateGlobalMessage, !deprecateGlobal, {
id: 'ember-metal.binding',
until: '3.0.0',
url: 'http://emberjs.com/deprecations/v2.x#toc_ember-binding'
});
deprecate(deprecateOneWayMessage, !deprecateOneWay, {
id: 'ember-metal.binding',
until: '3.0.0',
url: 'http://emberjs.com/deprecations/v2.x#toc_ember-binding'
});
deprecate(deprecateAliasMessage, !deprecateAlias, {
id: 'ember-metal.binding',
until: '3.0.0',
url: 'http://emberjs.com/deprecations/v2.x#toc_ember-binding'
});
}

function mixinProperties(to, from) {
for (var key in from) {
if (from.hasOwnProperty(key)) {
Expand Down
54 changes: 45 additions & 9 deletions packages/ember-metal/tests/binding/connect_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,26 @@ testBoth('Connecting a binding between two properties', function(get, set) {
// a.bar -> a.foo
var binding = new Binding('foo', 'bar');

performTest(binding, a, a, get, set);
let deprecationMessage = '`Ember.Binding` is deprecated. Consider using an' +
' `alias` computed property instead.';

expectDeprecation(() => {
performTest(binding, a, a, get, set);
}, deprecationMessage);
});

testBoth('Connecting a oneWay binding raises a deprecation',
function(get, set) {
var a = { foo: 'FOO', bar: 'BAR' };

// a.bar -> a.foo
var binding = new Binding('foo', 'bar').oneWay();

let deprecationMessage = '`Ember.Binding` is deprecated. Since you' +
' are using a `oneWay` binding consider using a `readOnly` computed' +
' property instead.';

expectDeprecation(() => { binding.connect(a); }, deprecationMessage);
});

testBoth('Connecting a binding between two objects', function(get, set) {
Expand All @@ -64,7 +83,12 @@ testBoth('Connecting a binding between two objects', function(get, set) {
// b.bar -> a.foo
var binding = new Binding('foo', 'b.bar');

performTest(binding, a, b, get, set);
let deprecationMessage = '`Ember.Binding` is deprecated. Consider using an' +
' `alias` computed property instead.';

expectDeprecation(() => {
performTest(binding, a, b, get, set);
}, deprecationMessage);
});

testBoth('Connecting a binding to path', function(get, set) {
Expand All @@ -78,7 +102,12 @@ testBoth('Connecting a binding to path', function(get, set) {
// globalB.b.bar -> a.foo
var binding = new Binding('foo', 'GlobalB.b.bar');

performTest(binding, a, b, get, set);
let deprecationMessage = '`Ember.Binding` is deprecated. Since you' +
' are binding to a global consider using a service instead.';

expectDeprecation(() => {
performTest(binding, a, b, get, set);
}, deprecationMessage);

// make sure modifications update
b = { bar: 'BIFF' };
Expand All @@ -97,11 +126,15 @@ testBoth('Calling connect more than once', function(get, set) {
// b.bar -> a.foo
var binding = new Binding('foo', 'b.bar');

performTest(binding, a, b, get, set, function () {
binding.connect(a);
let deprecationMessage = '`Ember.Binding` is deprecated. Consider using an' +
' `alias` computed property instead.';

binding.connect(a);
});
expectDeprecation(() => {
performTest(binding, a, b, get, set, function () {
binding.connect(a);
binding.connect(a);
});
}, deprecationMessage);
});

QUnit.test('inherited bindings should sync on create', function() {
Expand All @@ -111,10 +144,13 @@ QUnit.test('inherited bindings should sync on create', function() {
bind(this, 'foo', 'bar.baz');
};

a = new A();
let deprecationMessage = '`Ember.Binding` is deprecated. Consider using an' +
' `alias` computed property instead.';

expectDeprecation(() => { a = new A(); }, deprecationMessage);

set(a, 'bar', { baz: 'BAZ' });
});

equal(get(a, 'foo'), 'BAZ', 'should have synced binding on new obj');
});

45 changes: 39 additions & 6 deletions packages/ember-metal/tests/binding/sync_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@ testBoth('bindings should not sync twice in a single run loop', function(get, se
b = {
a: a
};
bind(b, 'foo', 'a.foo');

let deprecationMessage = '`Ember.Binding` is deprecated. Consider' +
' using an `alias` computed property instead.';

expectDeprecation(() => {
bind(b, 'foo', 'a.foo');
}, deprecationMessage);
});

// reset after initial binding synchronization
Expand Down Expand Up @@ -68,7 +74,13 @@ testBoth('bindings should not infinite loop if computed properties return object
b = {
a: a
};
bind(b, 'foo', 'a.foo');

let deprecationMessage = '`Ember.Binding` is deprecated. Consider' +
' using an `alias` computed property instead.';

expectDeprecation(() => {
bind(b, 'foo', 'a.foo');
}, deprecationMessage);
});

deepEqual(get(b, 'foo'), ['foo', 'bar'], 'the binding should sync');
Expand All @@ -86,12 +98,21 @@ testBoth('bindings should do the right thing when observers trigger bindings in
b = {
a: a
};
bind(b, 'foo', 'a.foo');

let deprecationMessage = '`Ember.Binding` is deprecated. Consider' +
' using an `alias` computed property instead.';

expectDeprecation(() => {
bind(b, 'foo', 'a.foo');
}, deprecationMessage);

c = {
a: a
};
bind(c, 'foo', 'a.foo');

expectDeprecation(() => {
bind(c, 'foo', 'a.foo');
}, deprecationMessage);
});

addObserver(b, 'foo', function() {
Expand All @@ -116,7 +137,13 @@ testBoth('bindings should not try to sync destroyed objects', function(get, set)
b = {
a: a
};
bind(b, 'foo', 'a.foo');

let deprecationMessage = '`Ember.Binding` is deprecated. Consider' +
' using an `alias` computed property instead.';

expectDeprecation(() => {
bind(b, 'foo', 'a.foo');
}, deprecationMessage);
});

run(function() {
Expand All @@ -133,7 +160,13 @@ testBoth('bindings should not try to sync destroyed objects', function(get, set)
b = {
a: a
};
bind(b, 'foo', 'a.foo');

let deprecationMessage = '`Ember.Binding` is deprecated. Consider' +
' using an `alias` computed property instead.';

expectDeprecation(() => {
bind(b, 'foo', 'a.foo');
}, deprecationMessage);
});

run(function() {
Expand Down
14 changes: 12 additions & 2 deletions packages/ember-runtime/tests/ext/mixin_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ QUnit.test('Defining a property ending in Binding should setup binding when appl
var obj = { bar: { baz: 'BIFF' } };

run(function() {
MyMixin.apply(obj);
let deprecationMessage = '`Ember.Binding` is deprecated. Consider' +
' using an `alias` computed property instead.';

expectDeprecation(() => {
MyMixin.apply(obj);
}, deprecationMessage);
});

ok(get(obj, 'fooBinding') instanceof Binding, 'should be a binding object');
Expand All @@ -33,7 +38,12 @@ QUnit.test('Defining a property ending in Binding should apply to prototype chil
obj = { bar: { baz: 'BIFF' } };

run(function() {
MyMixin.apply(obj);
let deprecationMessage = '`Ember.Binding` is deprecated. Consider' +
' using an `alias` computed property instead.';

expectDeprecation(() => {
MyMixin.apply(obj);
}, deprecationMessage);
});


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,9 +528,14 @@ QUnit.test('nested dependent keys should propagate after they update', function(
})
});

bindObj = ObservableObject.extend({
priceBinding: 'DepObj.price'
}).create();
let deprecationMessage = '`Ember.Binding` is deprecated. Since you' +
' are binding to a global consider using a service instead.';

expectDeprecation(() => {
bindObj = ObservableObject.extend({
priceBinding: 'DepObj.price'
}).create();
}, deprecationMessage);
});

equal(bindObj.get('price'), 5, 'precond - binding propagates');
Expand Down Expand Up @@ -835,7 +840,7 @@ QUnit.test('removing an observer inside of an observer shouldn’t cause any pro



QUnit.module('Bind function ', {
QUnit.module('Bind function', {
setup() {
objectA = ObservableObject.create({
name: 'Sproutcore',
Expand Down Expand Up @@ -865,7 +870,12 @@ QUnit.module('Bind function ', {
QUnit.test('should bind property with method parameter as undefined', function() {
// creating binding
run(function() {
objectA.bind('name', 'Namespace.objectB.normal', undefined);
let deprecationMessage = '`Ember.Binding` is deprecated. Since you' +
' are binding to a global consider using a service instead.';

expectDeprecation(() => {
objectA.bind('name', 'Namespace.objectB.normal', undefined);
}, deprecationMessage);
});

// now make a change to see if the binding triggers.
Expand Down
Loading

0 comments on commit 3cfc961

Please sign in to comment.