diff --git a/packages/ember-glimmer/tests/integration/binding_integration_test.js b/packages/ember-glimmer/tests/integration/binding_integration_test.js deleted file mode 100644 index b6d17b8a55a..00000000000 --- a/packages/ember-glimmer/tests/integration/binding_integration_test.js +++ /dev/null @@ -1,54 +0,0 @@ -import { RenderingTest, moduleFor } from '../utils/test-case'; -import { Component } from '../utils/helpers'; -import { set, Binding } from 'ember-metal'; - -moduleFor('Binding integration tests', class extends RenderingTest { - ['@test should accept bindings as a string or an Ember.binding']() { - let FooBarComponent = Component.extend({ - twoWayTestBinding: Binding.from('direction'), - stringTestBinding: 'direction', - twoWayObjectTestBinding: Binding.from('displacement.distance'), - stringObjectTestBinding: 'displacement.distance' - }); - - this.registerComponent('foo-bar', { - ComponentClass: FooBarComponent, - template: 'two way: {{twoWayTest}}, string: {{stringTest}}, object: {{twoWayObjectTest}}, string object: {{stringObjectTest}}' - }); - - expectDeprecation(() => { - this.render('{{foo-bar direction=direction displacement=displacement}}', { - direction: 'down', - displacement: { - distance: 10 - } - }); - }, /`Ember\.Binding` is deprecated/); - - this.assertText('two way: down, string: down, object: 10, string object: 10'); - - this.assertStableRerender(); - - this.runTask(() => set(this.context, 'direction', 'up')); - - this.assertText('two way: up, string: up, object: 10, string object: 10'); - - this.runTask(() => set(this.context, 'displacement.distance', 20)); - - this.assertText('two way: up, string: up, object: 20, string object: 20'); - - this.runTask(() => { - set(this.context, 'direction', 'right'); - set(this.context, 'displacement.distance', 30); - }); - - this.assertText('two way: right, string: right, object: 30, string object: 30'); - - this.runTask(() => { - set(this.context, 'direction', 'down'); - set(this.context, 'displacement', { distance: 10 }); - }); - - this.assertText('two way: down, string: down, object: 10, string object: 10'); - } -}); diff --git a/packages/ember-metal/lib/binding.js b/packages/ember-metal/lib/binding.js deleted file mode 100644 index 3132266b735..00000000000 --- a/packages/ember-metal/lib/binding.js +++ /dev/null @@ -1,504 +0,0 @@ -import { guidFor } from 'ember-utils'; -import Logger from 'ember-console'; -import { context, ENV } from 'ember-environment'; -import run from './run_loop'; -import { assert, deprecate } from 'ember-debug'; -import { get } from './property_get'; -import { trySet } from './property_set'; -import { addListener } from './events'; -import { - addObserver, - removeObserver, - _suspendObserver -} from './observer'; -import { - isGlobalPath, - getFirstKey, - getTailPath -} from './path_cache'; - -/** -@module ember -*/ - -// .......................................................... -// BINDING -// - -class Binding { - constructor(toPath, fromPath) { - // Configuration - this._from = fromPath; - this._to = toPath; - this._oneWay = undefined; - - // State - this._direction = undefined; - this._readyToSync = undefined; - this._fromObj = undefined; - this._fromPath = undefined; - this._toObj = undefined; - } - - /** - @class Binding - @namespace Ember - @deprecated See https://emberjs.com/deprecations/v2.x#toc_ember-binding - @public - */ - - /** - This copies the Binding so it can be connected to another object. - - @method copy - @return {Ember.Binding} `this` - @public - */ - copy() { - let copy = new Binding(this._to, this._from); - if (this._oneWay) { copy._oneWay = true; } - return copy; - } - - // .......................................................... - // CONFIG - // - - /** - This will set `from` property path to the specified value. It will not - attempt to resolve this property path to an actual object until you - connect the binding. - - The binding will search for the property path starting at the root object - you pass when you `connect()` the binding. It follows the same rules as - `get()` - see that method for more information. - - @method from - @param {String} path The property path to connect to. - @return {Ember.Binding} `this` - @public - */ - from(path) { - this._from = path; - return this; - } - - /** - This will set the `to` property path to the specified value. It will not - attempt to resolve this property path to an actual object until you - connect the binding. - - The binding will search for the property path starting at the root object - you pass when you `connect()` the binding. It follows the same rules as - `get()` - see that method for more information. - - @method to - @param {String|Tuple} path A property path or tuple. - @return {Ember.Binding} `this` - @public - */ - to(path) { - this._to = path; - return this; - } - - /** - Configures the binding as one way. A one-way binding will relay changes - on the `from` side to the `to` side, but not the other way around. This - means that if you change the `to` side directly, the `from` side may have - a different value. - - @method oneWay - @return {Ember.Binding} `this` - @public - */ - oneWay() { - this._oneWay = true; - return this; - } - - /** - @method toString - @return {String} string representation of binding - @public - */ - toString() { - let oneWay = this._oneWay ? '[oneWay]' : ''; - return `Ember.Binding<${guidFor(this)}>(${this._from} -> ${this._to})${oneWay}`; - } - - // .......................................................... - // CONNECT AND SYNC - // - - /** - Attempts to connect this binding instance so that it can receive and relay - changes. This method will raise an exception if you have not set the - from/to properties yet. - - @method connect - @param {Object} obj The root object for this binding. - @return {Ember.Binding} `this` - @public - */ - connect(obj) { - assert('Must pass a valid object to Ember.Binding.connect()', !!obj); - - 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); - possibleGlobal = context.lookup[name]; - - if (possibleGlobal) { - fromObj = possibleGlobal; - fromPath = getTailPath(this._from); - } - } - - if (fromObj === undefined) { - fromObj = obj; - fromPath = this._from; - } - - trySet(obj, this._to, get(fromObj, fromPath)); - - // Add an observer on the object to be notified when the binding should be updated. - addObserver(fromObj, fromPath, this, 'fromDidChange'); - - // If the binding is a two-way binding, also set up an observer on the target. - if (!this._oneWay) { - addObserver(obj, this._to, this, 'toDidChange'); - } - - addListener(obj, 'willDestroy', this, 'disconnect'); - - fireDeprecations( - obj, - this._to, - this._from, - possibleGlobal, - this._oneWay, - (!possibleGlobal && !this._oneWay) - ); - - this._readyToSync = true; - this._fromObj = fromObj; - this._fromPath = fromPath; - this._toObj = obj; - - return this; - } - - /** - Disconnects the binding instance. Changes will no longer be relayed. You - will not usually need to call this method. - - @method disconnect - @return {Ember.Binding} `this` - @public - */ - disconnect() { - assert('Must pass a valid object to Ember.Binding.disconnect()', !!this._toObj); - - // Remove an observer on the object so we're no longer notified of - // changes that should update bindings. - removeObserver(this._fromObj, this._fromPath, this, 'fromDidChange'); - - // If the binding is two-way, remove the observer from the target as well. - if (!this._oneWay) { - removeObserver(this._toObj, this._to, this, 'toDidChange'); - } - - this._readyToSync = false; // Disable scheduled syncs... - return this; - } - - // .......................................................... - // PRIVATE - // - - /* Called when the from side changes. */ - fromDidChange(target) { // eslint-disable-line no-unused-vars - this._scheduleSync('fwd'); - } - - /* Called when the to side changes. */ - toDidChange(target) { // eslint-disable-line no-unused-vars - this._scheduleSync('back'); - } - - _scheduleSync(dir) { - let existingDir = this._direction; - - // If we haven't scheduled the binding yet, schedule it. - if (existingDir === undefined) { - run.schedule('sync', this, '_sync'); - this._direction = dir; - } - - // If both a 'back' and 'fwd' sync have been scheduled on the same object, - // default to a 'fwd' sync so that it remains deterministic. - if (existingDir === 'back' && dir === 'fwd') { - this._direction = 'fwd'; - } - } - - _sync() { - let log = ENV.LOG_BINDINGS; - - let toObj = this._toObj; - - // Don't synchronize destroyed objects or disconnected bindings. - if (toObj.isDestroyed || !this._readyToSync) { return; } - - // Get the direction of the binding for the object we are - // synchronizing from. - let direction = this._direction; - - let fromObj = this._fromObj; - let fromPath = this._fromPath; - - this._direction = undefined; - - // If we're synchronizing from the remote object... - if (direction === 'fwd') { - let fromValue = get(fromObj, fromPath); - if (log) { - Logger.log(' ', this.toString(), '->', fromValue, fromObj); - } - if (this._oneWay) { - trySet(toObj, this._to, fromValue); - } else { - _suspendObserver(toObj, this._to, this, 'toDidChange', function() { - trySet(toObj, this._to, fromValue); - }); - } - // If we're synchronizing *to* the remote object. - } else if (direction === 'back') { - let toValue = get(toObj, this._to); - if (log) { - Logger.log(' ', this.toString(), '<-', toValue, toObj); - } - _suspendObserver(fromObj, fromPath, this, 'fromDidChange', () => { - trySet(fromObj, fromPath, toValue); - }); - } - } -} - -function fireDeprecations(obj, toPath, fromPath, 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.'; - - let objectInfo = `The \`${toPath}\` property of \`${obj}\` is an \`Ember.Binding\` connected to \`${fromPath}\`, but `; - deprecate(objectInfo + deprecateGlobalMessage, !deprecateGlobal, { - id: 'ember-metal.binding', - until: '3.0.0', - url: 'https://emberjs.com/deprecations/v2.x#toc_ember-binding' - }); - deprecate(objectInfo + deprecateOneWayMessage, !deprecateOneWay, { - id: 'ember-metal.binding', - until: '3.0.0', - url: 'https://emberjs.com/deprecations/v2.x#toc_ember-binding' - }); - deprecate(objectInfo + deprecateAliasMessage, !deprecateAlias, { - id: 'ember-metal.binding', - until: '3.0.0', - url: 'https://emberjs.com/deprecations/v2.x#toc_ember-binding' - }); -} - -function mixinProperties(to, from) { - for (let key in from) { - if (from.hasOwnProperty(key)) { - to[key] = from[key]; - } - } -} - -mixinProperties(Binding, { - - /* - See `Ember.Binding.from`. - - @method from - @static - */ - from(from) { - let C = this; - return new C(undefined, from); - }, - - /* - See `Ember.Binding.to`. - - @method to - @static - */ - to(to) { - let C = this; - return new C(to, undefined); - } -}); -/** - An `Ember.Binding` connects the properties of two objects so that whenever - the value of one property changes, the other property will be changed also. - - ## Automatic Creation of Bindings with `/^*Binding/`-named Properties. - - You do not usually create Binding objects directly but instead describe - bindings in your class or object definition using automatic binding - detection. - - Properties ending in a `Binding` suffix will be converted to `Ember.Binding` - instances. The value of this property should be a string representing a path - to another object or a custom binding instance created using Binding helpers - (see "One Way Bindings"): - - ``` - valueBinding: "MyApp.someController.title" - ``` - - This will create a binding from `MyApp.someController.title` to the `value` - property of your object instance automatically. Now the two values will be - kept in sync. - - ## One Way Bindings - - One especially useful binding customization you can use is the `oneWay()` - helper. This helper tells Ember that you are only interested in - receiving changes on the object you are binding from. For example, if you - are binding to a preference and you want to be notified if the preference - has changed, but your object will not be changing the preference itself, you - could do: - - ``` - bigTitlesBinding: Ember.Binding.oneWay("MyApp.preferencesController.bigTitles") - ``` - - This way if the value of `MyApp.preferencesController.bigTitles` changes the - `bigTitles` property of your object will change also. However, if you - change the value of your `bigTitles` property, it will not update the - `preferencesController`. - - One way bindings are almost twice as fast to setup and twice as fast to - execute because the binding only has to worry about changes to one side. - - You should consider using one way bindings anytime you have an object that - may be created frequently and you do not intend to change a property; only - to monitor it for changes (such as in the example above). - - ## Adding Bindings Manually - - All of the examples above show you how to configure a custom binding, but the - result of these customizations will be a binding template, not a fully active - Binding instance. The binding will actually become active only when you - instantiate the object the binding belongs to. It is useful, however, to - understand what actually happens when the binding is activated. - - For a binding to function it must have at least a `from` property and a `to` - property. The `from` property path points to the object/key that you want to - bind from while the `to` path points to the object/key you want to bind to. - - When you define a custom binding, you are usually describing the property - you want to bind from (such as `MyApp.someController.value` in the examples - above). When your object is created, it will automatically assign the value - you want to bind `to` based on the name of your binding key. In the - examples above, during init, Ember objects will effectively call - something like this on your binding: - - ```javascript - binding = Ember.Binding.from("valueBinding").to("value"); - ``` - - This creates a new binding instance based on the template you provide, and - sets the to path to the `value` property of the new object. Now that the - binding is fully configured with a `from` and a `to`, it simply needs to be - connected to become active. This is done through the `connect()` method: - - ```javascript - binding.connect(this); - ``` - - Note that when you connect a binding you pass the object you want it to be - connected to. This object will be used as the root for both the from and - to side of the binding when inspecting relative paths. This allows the - binding to be automatically inherited by subclassed objects as well. - - This also allows you to bind between objects using the paths you declare in - `from` and `to`: - - ```javascript - // Example 1 - binding = Ember.Binding.from("App.someObject.value").to("value"); - binding.connect(this); - - // Example 2 - binding = Ember.Binding.from("parentView.value").to("App.someObject.value"); - binding.connect(this); - ``` - - Now that the binding is connected, it will observe both the from and to side - and relay changes. - - If you ever needed to do so (you almost never will, but it is useful to - understand this anyway), you could manually create an active binding by - using the `Ember.bind()` helper method. (This is the same method used by - to setup your bindings on objects): - - ```javascript - Ember.bind(MyApp.anotherObject, "value", "MyApp.someController.value"); - ``` - - Both of these code fragments have the same effect as doing the most friendly - form of binding creation like so: - - ```javascript - MyApp.anotherObject = Ember.Object.create({ - valueBinding: "MyApp.someController.value", - - // OTHER CODE FOR THIS OBJECT... - }); - ``` - - Ember's built in binding creation method makes it easy to automatically - create bindings for you. You should always use the highest-level APIs - available, even if you understand how it works underneath. - - @class Binding - @namespace Ember - @since Ember 0.9 - @public -*/ -// Ember.Binding = Binding; ES6TODO: where to put this? - - -/** - Global helper method to create a new binding. Just pass the root object - along with a `to` and `from` path to create and connect the binding. - - @method bind - @for Ember - @param {Object} obj The root object of the transform. - @param {String} to The path to the 'to' side of the binding. - Must be relative to obj. - @param {String} from The path to the 'from' side of the binding. - Must be relative to obj or a global path. - @return {Ember.Binding} binding instance - @public -*/ -export function bind(obj, to, from) { - return new Binding(to, from).connect(obj); -} - -export { - Binding -}; diff --git a/packages/ember-metal/lib/index.js b/packages/ember-metal/lib/index.js index 04d44b4409c..b0ee3328499 100644 --- a/packages/ember-metal/lib/index.js +++ b/packages/ember-metal/lib/index.js @@ -118,12 +118,7 @@ export { REQUIRED, hasUnprocessedMixins, clearUnprocessedMixins, - detectBinding } from './mixin'; -export { - Binding, - bind -} from './binding'; export { isGlobalPath } from './path_cache'; diff --git a/packages/ember-metal/lib/meta.js b/packages/ember-metal/lib/meta.js index 2c03a7e5cf7..6813b00b19e 100644 --- a/packages/ember-metal/lib/meta.js +++ b/packages/ember-metal/lib/meta.js @@ -10,6 +10,7 @@ import { DESCRIPTOR_TRAP, EMBER_METAL_ES5_GETTERS, MANDATORY_SETTER } from 'embe import { removeChainWatcher } from './chains'; +import { ENV } from 'ember-environment'; let counters; if (DEBUG) { @@ -52,7 +53,9 @@ export class Meta { this._watching = undefined; this._mixins = undefined; - this._bindings = undefined; + if (ENV._ENABLE_BINDING_SUPPORT) { + this._bindings = undefined; + } this._values = undefined; this._deps = undefined; this._chainWatchers = undefined; @@ -362,6 +365,7 @@ export class Meta { } writeBindings(subkey, value) { + assert('Cannot invoke `meta.writeBindings` when EmberENV._ENABLE_BINDING_SUPPORT is not set', ENV._ENABLE_BINDING_SUPPORT); assert(`Cannot add a binding for \`${subkey}\` on \`${toString(this.source)}\` after it has been destroyed.`, !this.isMetaDestroyed()); let map = this._getOrCreateOwnMap('_bindings'); @@ -369,10 +373,13 @@ export class Meta { } peekBindings(subkey) { + assert('Cannot invoke `meta.peekBindings` when EmberENV._ENABLE_BINDING_SUPPORT is not set', ENV._ENABLE_BINDING_SUPPORT); return this._findInherited('_bindings', subkey); } forEachBindings(fn) { + assert('Cannot invoke `meta.forEachBindings` when EmberENV._ENABLE_BINDING_SUPPORT is not set', ENV._ENABLE_BINDING_SUPPORT); + let pointer = this; let seen; while (pointer !== undefined) { @@ -391,6 +398,7 @@ export class Meta { } clearBindings() { + assert('Cannot invoke `meta.clearBindings` when EmberENV._ENABLE_BINDING_SUPPORT is not set', ENV._ENABLE_BINDING_SUPPORT); assert(`Cannot clear bindings on \`${toString(this.source)}\` after it has been destroyed.`, !this.isMetaDestroyed()); this._bindings = undefined; } diff --git a/packages/ember-metal/lib/mixin.js b/packages/ember-metal/lib/mixin.js index b44f201a69b..7fae532cc37 100644 --- a/packages/ember-metal/lib/mixin.js +++ b/packages/ember-metal/lib/mixin.js @@ -25,7 +25,6 @@ import { defineProperty } from './properties'; import { ComputedProperty } from './computed'; -import { Binding } from './binding'; import { addObserver, removeObserver, @@ -258,39 +257,6 @@ function mergeMixins(mixins, meta, descs, values, base, keys) { } } -export function detectBinding(key) { - let length = key.length; - - return length > 7 && key.charCodeAt(length - 7) === 66 && key.indexOf('inding', length - 6) !== -1; -} -// warm both paths of above function -detectBinding('notbound'); -detectBinding('fooBinding'); - -function connectBindings(obj, meta) { - // TODO Mixin.apply(instance) should disconnect binding if exists - meta.forEachBindings((key, binding) => { - if (binding) { - let to = key.slice(0, -7); // strip Binding off end - if (binding instanceof Binding) { - binding = binding.copy(); // copy prototypes' instance - binding.to(to); - } else { // binding is string path - binding = new Binding(to, binding); - } - binding.connect(obj); - obj[key] = binding; - } - }); - // mark as applied - meta.clearBindings(); -} - -function finishPartial(obj, meta) { - connectBindings(obj, meta === undefined ? metaFor(obj) : meta); - return obj; -} - function followAlias(obj, desc, descs, values) { let altKey = desc.methodName; let value; @@ -372,15 +338,15 @@ function applyMixin(obj, mixins, partial) { replaceObserversAndListeners(obj, key, obj[key], value); } - if (detectBinding(key)) { + if (ENV._ENABLE_BINDING_SUPPORT && Mixin.detectBinding(key)) { meta.writeBindings(key, value); } defineProperty(obj, key, desc, value, meta); } - if (!partial) { // don't apply to prototype - finishPartial(obj, meta); + if (ENV._ENABLE_BINDING_SUPPORT && !partial) { // don't apply to prototype + Mixin.finishPartial(obj, meta); } return obj; @@ -625,7 +591,12 @@ export default class Mixin { } Mixin._apply = applyMixin; -Mixin.finishPartial = finishPartial; +if (ENV._ENABLE_BINDING_SUPPORT) { + // slotting this so that the legacy addon can add the function here + // without triggering an error due to the Object.seal done below + Mixin.finishPartial = null; + Mixin.detectBinding = null; +} let MixinPrototype = Mixin.prototype; MixinPrototype.toString = Object.toString; diff --git a/packages/ember-metal/tests/binding/connect_test.js b/packages/ember-metal/tests/binding/connect_test.js deleted file mode 100644 index f85da185994..00000000000 --- a/packages/ember-metal/tests/binding/connect_test.js +++ /dev/null @@ -1,132 +0,0 @@ -import { context } from 'ember-environment'; -import { testBoth } from 'internal-test-helpers'; -import { - Binding, - bind, - run, - set, - get -} from '../..'; - -function performTest(binding, a, b, get, set, connect) { - if (connect === undefined) { - connect = () => binding.connect(a); - } - - let { assert } = QUnit.config.current; - - assert.ok(!run.currentRunLoop, 'performTest should not have a currentRunLoop'); - - assert.equal(get(a, 'foo'), 'FOO', 'a should not have changed'); - assert.equal(get(b, 'bar'), 'BAR', 'b should not have changed'); - - connect(); - - assert.equal(get(a, 'foo'), 'BAR', 'a should have changed'); - assert.equal(get(b, 'bar'), 'BAR', 'b should have changed'); - // - // make sure changes sync both ways - run(() => set(b, 'bar', 'BAZZ')); - assert.equal(get(a, 'foo'), 'BAZZ', 'a should have changed'); - - run(() => set(a, 'foo', 'BARF')); - assert.equal(get(b, 'bar'), 'BARF', 'a should have changed'); -} - -let originalLookup, lookup, GlobalB; - -QUnit.module('Ember.Binding', { - beforeEach() { - originalLookup = context.lookup; - context.lookup = lookup = {}; - }, - afterEach() { - lookup = null; - context.lookup = originalLookup; - } -}); - -testBoth('Connecting a binding between two properties', function(get, set) { - let a = { foo: 'FOO', bar: 'BAR' }; - - // a.bar -> a.foo - let binding = new Binding('foo', 'bar'); - - expectDeprecation(() => { - performTest(binding, a, a, get, set); - }, /`Ember\.Binding` is deprecated./); -}); - -testBoth('Connecting a oneWay binding raises a deprecation', function() { - let a = { foo: 'FOO', bar: 'BAR', toString() { return ''; } }; - - // a.bar -> a.foo - let binding = new Binding('foo', 'bar').oneWay(); - - expectDeprecation(() => { binding.connect(a); }, /`Ember.Binding` is deprecated/); -}); - -testBoth('Connecting a binding between two objects', function(get, set) { - let b = { bar: 'BAR' }; - let a = { foo: 'FOO', b: b }; - - // b.bar -> a.foo - let binding = new Binding('foo', 'b.bar'); - - expectDeprecation(() => { - performTest(binding, a, b, get, set); - }, /`Ember\.Binding` is deprecated./); -}); - -testBoth('Connecting a binding to path', function(get, set, assert) { - let a = { foo: 'FOO' }; - lookup['GlobalB'] = GlobalB = { - b: { bar: 'BAR' } - }; - - let b = get(GlobalB, 'b'); - - // globalB.b.bar -> a.foo - let binding = new Binding('foo', 'GlobalB.b.bar'); - - expectDeprecation(() => { - performTest(binding, a, b, get, set); - }, /`Ember\.Binding` is deprecated./); - - // make sure modifications update - b = { bar: 'BIFF' }; - - run(() => set(GlobalB, 'b', b)); - - assert.equal(get(a, 'foo'), 'BIFF', 'a should have changed'); -}); - -testBoth('Calling connect more than once', function(get, set) { - let b = { bar: 'BAR' }; - let a = { foo: 'FOO', b: b }; - - // b.bar -> a.foo - let binding = new Binding('foo', 'b.bar'); - - expectDeprecation(() => { - performTest(binding, a, b, get, set, () => { - binding.connect(a); - binding.connect(a); - }); - }, /`Ember\.Binding` is deprecated./); -}); - -QUnit.test('inherited bindings should sync on create', function(assert) { - let a; - run(() => { - function A() { - bind(this, 'foo', 'bar.baz'); - } - - expectDeprecation(() => a = new A(), /`Ember\.Binding` is deprecated/); - - set(a, 'bar', { baz: 'BAZ' }); - }); - - assert.equal(get(a, 'foo'), 'BAZ', 'should have synced binding on new obj'); -}); diff --git a/packages/ember-metal/tests/binding/sync_test.js b/packages/ember-metal/tests/binding/sync_test.js deleted file mode 100644 index d9fa0ded944..00000000000 --- a/packages/ember-metal/tests/binding/sync_test.js +++ /dev/null @@ -1,155 +0,0 @@ -import { testBoth } from 'internal-test-helpers'; -import { - run, - addObserver, - bind, - computed, - defineProperty, - propertyWillChange, - propertyDidChange -} from '../..'; - -QUnit.module('system/binding/sync_test.js'); - -testBoth('bindings should not sync twice in a single run loop', function(get, set, assert) { - let a, b, setValue; - let setCalled = 0; - let getCalled = 0; - - run(() => { - a = {}; - - defineProperty(a, 'foo', computed({ - get() { - getCalled++; - return setValue; - }, - set(key, value) { - setCalled++; - propertyWillChange(this, key); - setValue = value; - propertyDidChange(this, key); - return value; - } - }).volatile()); - - b = { - a: a - }; - - expectDeprecation(() => bind(b, 'foo', 'a.foo'), /`Ember.Binding` is deprecated/); - }); - - // reset after initial binding synchronization - getCalled = 0; - - run(() => { - set(a, 'foo', 'trollface'); - }); - - assert.equal(get(b, 'foo'), 'trollface', 'the binding should sync'); - assert.equal(setCalled, 1, 'Set should only be called once'); - assert.equal(getCalled, 1, 'Get should only be called once'); -}); - -testBoth('bindings should not infinite loop if computed properties return objects', function(get, set, assert) { - let a, b; - let getCalled = 0; - - run(() => { - a = {}; - - defineProperty(a, 'foo', computed(function() { - getCalled++; - if (getCalled > 1000) { - throw 'infinite loop detected'; - } - return ['foo', 'bar']; - })); - - b = { - a: a - }; - - expectDeprecation(() => bind(b, 'foo', 'a.foo'), /`Ember.Binding` is deprecated/); - }); - - assert.deepEqual(get(b, 'foo'), ['foo', 'bar'], 'the binding should sync'); - assert.equal(getCalled, 1, 'Get should only be called once'); -}); - -testBoth('bindings should do the right thing when observers trigger bindings in the opposite direction', function(get, set, assert) { - let a, b, c; - - run(() => { - a = { - foo: 'trololol' - }; - - b = { - a: a - }; - - let deprecationMessage = /`Ember.Binding` is deprecated/; - - expectDeprecation(() => bind(b, 'foo', 'a.foo'), deprecationMessage); - - c = { - a: a - }; - - expectDeprecation(() => { - bind(c, 'foo', 'a.foo'); - }, deprecationMessage); - }); - - addObserver(b, 'foo', () => set(c, 'foo', 'what is going on')); - - run(() => set(a, 'foo', 'trollface')); - - assert.equal(get(a, 'foo'), 'what is going on'); -}); - -testBoth('bindings should not try to sync destroyed objects', function(get, set, assert) { - let a, b; - - run(() => { - a = { - foo: 'trololol' - }; - - b = { - a: a - }; - - let deprecationMessage = /`Ember.Binding` is deprecated/; - - expectDeprecation(() => bind(b, 'foo', 'a.foo'), deprecationMessage); - }); - - run(() => { - set(a, 'foo', 'trollface'); - set(b, 'isDestroyed', true); - assert.ok(true, 'should not raise'); - }); - - run(() => { - a = { - foo: 'trololol' - }; - - b = { - a: a - }; - - let deprecationMessage = /`Ember.Binding` is deprecated/; - - expectDeprecation(() => bind(b, 'foo', 'a.foo'), deprecationMessage); - }); - - run(() => { - set(b, 'foo', 'trollface'); - set(a, 'isDestroyed', true); - assert.ok(true, 'should not raise'); - }); -}); diff --git a/packages/ember-runtime/lib/system/core_object.js b/packages/ember-runtime/lib/system/core_object.js index b84e35c7258..6d9b51b452e 100644 --- a/packages/ember-runtime/lib/system/core_object.js +++ b/packages/ember-runtime/lib/system/core_object.js @@ -21,7 +21,6 @@ import { peekMeta, finishChains, sendEvent, - detectBinding, Mixin, REQUIRED, defineProperty, @@ -43,7 +42,6 @@ import { MANDATORY_SETTER } from 'ember/features'; const schedule = run.schedule; const applyMixin = Mixin._apply; -const finishPartial = Mixin.finishPartial; const reopen = Mixin.prototype.reopen; export const POST_INIT = symbol('POST_INIT'); @@ -107,7 +105,7 @@ function makeCtor() { let keyName = keyNames[j]; let value = properties[keyName]; - if (detectBinding(keyName)) { + if (ENV._ENABLE_BINDING_SUPPORT && Mixin.detectBinding(keyName)) { m.writeBindings(keyName, value); } @@ -161,7 +159,9 @@ function makeCtor() { } } - finishPartial(this, m); + if (ENV._ENABLE_BINDING_SUPPORT) { + Mixin.finishPartial(this, m); + } this.init(...arguments); diff --git a/packages/ember-runtime/tests/ext/mixin_test.js b/packages/ember-runtime/tests/ext/mixin_test.js deleted file mode 100644 index d2ea22d9cb9..00000000000 --- a/packages/ember-runtime/tests/ext/mixin_test.js +++ /dev/null @@ -1,47 +0,0 @@ -import { set, get, Mixin, Binding, run } from 'ember-metal'; - -QUnit.module('system/mixin/binding_test'); - -QUnit.test('Defining a property ending in Binding should setup binding when applied', function(assert) { - let MyMixin = Mixin.create({ - fooBinding: 'bar.baz' - }); - - let obj = { bar: { baz: 'BIFF' } }; - - run(() => { - let deprecationMessage = /`Ember.Binding` is deprecated/; - - expectDeprecation(() => { - MyMixin.apply(obj); - }, deprecationMessage); - }); - - assert.ok(get(obj, 'fooBinding') instanceof Binding, 'should be a binding object'); - assert.equal(get(obj, 'foo'), 'BIFF', 'binding should be created and synced'); -}); - -QUnit.test('Defining a property ending in Binding should apply to prototype children', function(assert) { - let MyMixin = run(() => { - return Mixin.create({ - fooBinding: 'bar.baz' - }); - }); - - let obj = { bar: { baz: 'BIFF' } }; - - run(function() { - let deprecationMessage = /`Ember.Binding` is deprecated/; - - expectDeprecation(() => { - MyMixin.apply(obj); - }, deprecationMessage); - }); - - - let obj2 = Object.create(obj); - run(() => set(get(obj2, 'bar'), 'baz', 'BARG')); - - assert.ok(get(obj2, 'fooBinding') instanceof Binding, 'should be a binding object'); - assert.equal(get(obj2, 'foo'), 'BARG', 'binding should be created and synced'); -}); diff --git a/packages/ember-runtime/tests/legacy_1x/mixins/observable/observable_test.js b/packages/ember-runtime/tests/legacy_1x/mixins/observable/observable_test.js index c62a7463e6c..2b1c670747f 100644 --- a/packages/ember-runtime/tests/legacy_1x/mixins/observable/observable_test.js +++ b/packages/ember-runtime/tests/legacy_1x/mixins/observable/observable_test.js @@ -22,7 +22,6 @@ import { moduleFor, AbstractTestCase } from 'internal-test-helpers'; rule on using capital letters for property paths. * Removed test passing context to addObserver. context param is no longer supported. - * Changed calls to Ember.Binding.flushPendingChanges() -> run.sync() * removed test in observer around line 862 that expected key/value to be the last item in the chained path. Should be root and chained path @@ -152,24 +151,24 @@ moduleFor('Ember.get()', class extends AbstractTestCase { }); moduleFor('Ember.get() with paths', class extends AbstractTestCase { - + ['@test should return a property at a given path relative to the passed object'](assert) { var foo = ObservableObject.create({ bar: ObservableObject.extend({ baz: computed(function() { return 'blargh'; }).volatile() }).create() }); - + assert.equal(get(foo, 'bar.baz'), 'blargh'); } - + ['@test should return a property at a given path relative to the passed object - JavaScript hash'](assert) { var foo = { bar: { baz: 'blargh' } }; - + assert.equal(get(foo, 'bar.baz'), 'blargh'); } }); @@ -508,45 +507,6 @@ moduleFor('Computed properties', class extends AbstractTestCase { assert.equal(depObj.get('menuPrice'), 6, 'cache is properly invalidated after nested property changes'); } - ['@test nested dependent keys should propagate after they update'](assert) { - var bindObj; - run(function () { - lookup.DepObj = ObservableObject.extend({ - price: computed(function() { - return this.get('restaurant.menu.price'); - }).property('restaurant.menu.price') - }).create({ - restaurant: ObservableObject.create({ - menu: ObservableObject.create({ - price: 5 - }) - }) - }); - - expectDeprecation(() => { - bindObj = ObservableObject.extend({ - priceBinding: 'DepObj.price' - }).create(); - }, /`Ember.Binding` is deprecated/); - }); - - assert.equal(bindObj.get('price'), 5, 'precond - binding propagates'); - - run(function () { - lookup.DepObj.set('restaurant.menu.price', 10); - }); - - assert.equal(bindObj.get('price'), 10, 'binding propagates after a nested dependent keys updates'); - - run(function () { - lookup.DepObj.set('restaurant.menu', ObservableObject.create({ - price: 15 - })); - }); - - assert.equal(bindObj.get('price'), 15, 'binding propagates after a middle dependent keys updates'); - } - ['@test cacheable nested dependent keys should clear after their dependencies update'](assert) { assert.ok(true); @@ -829,72 +789,3 @@ moduleFor('object.removeObserver()', class extends AbstractTestCase { assert.equal(encounteredError, false); } }); - - -moduleFor('Bind function', class extends AbstractTestCase { - beforeEach() { - objectA = ObservableObject.create({ - name: 'Sproutcore', - location: 'Timbaktu' - }); - - objectB = ObservableObject.create({ - normal: 'value', - computed() { - this.normal = 'newValue'; - } - }); - - lookup = context.lookup = { - 'Namespace': { - objectA: objectA, - objectB: objectB - } - }; - } - - afterEach() { - context.lookup = originalLookup; - } - - ['@test should bind property with method parameter as undefined'](assert) { - // creating binding - run(function() { - expectDeprecation(() => { - objectA.bind('name', 'Namespace.objectB.normal', undefined); - }, /`Ember.Binding` is deprecated/); - }); - - // now make a change to see if the binding triggers. - run(function() { - objectB.set('normal', 'changedValue'); - }); - - // support new-style bindings if available - assert.equal('changedValue', objectA.get('name'), 'objectA.name is bound'); - } - - // .......................................................... - // SPECIAL CASES - // - - ['@test changing chained observer object to null should not raise exception'](assert) { - var obj = ObservableObject.create({ - foo: ObservableObject.create({ - bar: ObservableObject.create({ bat: 'BAT' }) - }) - }); - - var callCount = 0; - obj.foo.addObserver('bar.bat', obj, function() { - callCount++; - }); - - run(function() { - obj.foo.set('bar', null); - }); - - assert.equal(callCount, 1, 'changing bar should trigger observer'); - assert.expect(1); - } -}); \ No newline at end of file diff --git a/packages/ember-runtime/tests/legacy_1x/system/binding_test.js b/packages/ember-runtime/tests/legacy_1x/system/binding_test.js deleted file mode 100644 index be3792cfd86..00000000000 --- a/packages/ember-runtime/tests/legacy_1x/system/binding_test.js +++ /dev/null @@ -1,304 +0,0 @@ -import { context } from 'ember-environment'; -import { - get, - set, - run, - Binding, - bind, - observer as emberObserver -} from 'ember-metal'; -import EmberObject from '../../../system/object'; -import { moduleFor, AbstractTestCase } from 'internal-test-helpers'; - - -/* - NOTE: This test is adapted from the 1.x series of unit tests. The tests - are the same except for places where we intend to break the API we instead - validate that we warn the developer appropriately. - - CHANGES FROM 1.6: - - * All calls to run.sync() were changed to - run.sync() - - * Bindings no longer accept a root object as their second param. Instead - our test binding objects were put under a single object they could - originate from. - - * tests that inspected internal properties were removed. - - * converted foo.get/foo.set to use get/Ember.set - - * Removed tests for Binding.isConnected. Since binding instances are now - shared this property no longer makes sense. - - * Changed call calls for obj.bind(...) to bind(obj, ...); - - * Changed all calls to sc_super() to this._super(...arguments) - - * Changed all calls to disconnect() to pass the root object. - - * removed calls to Binding.destroy() as that method is no longer useful - (or defined) - - * changed use of T_STRING to 'string' -*/ - -// ======================================================================== -// Binding Tests -// ======================================================================== - -let TestNamespace, fromObject, toObject, binding, Bon1, bon2, root; // global variables -const originalLookup = context.lookup; -let lookup; - -moduleFor('basic object binding', class extends AbstractTestCase { - beforeEach() { - fromObject = EmberObject.create({ value: 'start' }); - toObject = EmberObject.create({ value: 'end' }); - root = { fromObject: fromObject, toObject: toObject }; - run(() => { - expectDeprecation(() => { - binding = bind(root, 'toObject.value', 'fromObject.value'); - }, /`Ember\.Binding` is deprecated./); - }); - } - - - ['@test binding should have synced on connect'](assert) { - assert.equal(get(toObject, 'value'), 'start', 'toObject.value should match fromObject.value'); - } - - ['@test fromObject change should propagate to toObject only after flush'](assert) { - run(() => { - set(fromObject, 'value', 'change'); - assert.equal(get(toObject, 'value'), 'start'); - }); - assert.equal(get(toObject, 'value'), 'change'); - } - - ['@test toObject change should propagate to fromObject only after flush'](assert) { - run(() => { - set(toObject, 'value', 'change'); - assert.equal(get(fromObject, 'value'), 'start'); - }); - assert.equal(get(fromObject, 'value'), 'change'); - } - - ['@test deferred observing during bindings'](assert) { - // setup special binding - fromObject = EmberObject.create({ - value1: 'value1', - value2: 'value2' - }); - - toObject = EmberObject.extend({ - observer: emberObserver('value1', 'value2', function() { - assert.equal(get(this, 'value1'), 'CHANGED', 'value1 when observer fires'); - assert.equal(get(this, 'value2'), 'CHANGED', 'value2 when observer fires'); - this.callCount++; - }) - }).create({ - value1: 'value1', - value2: 'value2', - - callCount: 0 - }); - - let root = { fromObject: fromObject, toObject: toObject }; - run(function () { - expectDeprecation(() => { - bind(root, 'toObject.value1', 'fromObject.value1'); - }, /`Ember\.Binding` is deprecated./); - - expectDeprecation(() => { - bind(root, 'toObject.value2', 'fromObject.value2'); - }, /`Ember\.Binding` is deprecated./); - - // change both value1 + value2, then flush bindings. observer should only - // fire after bindings are done flushing. - set(fromObject, 'value1', 'CHANGED'); - set(fromObject, 'value2', 'CHANGED'); - }); - - assert.equal(toObject.callCount, 2, 'should call observer twice'); - } - - ['@test binding disconnection actually works'](assert) { - binding.disconnect(root); - run(function () { - set(fromObject, 'value', 'change'); - }); - assert.equal(get(toObject, 'value'), 'start'); - } -}); -let first, second, third; // global variables - -// .......................................................... -// chained binding -// - -moduleFor('chained binding', class extends AbstractTestCase { - - beforeEach() { - run(function() { - first = EmberObject.create({ output: 'first' }); - - second = EmberObject.extend({ - inputDidChange: emberObserver('input', function() { - set(this, 'output', get(this, 'input')); - }) - }).create({ - input: 'second', - output: 'second' - }); - - third = EmberObject.create({ input: 'third' }); - - root = { first: first, second: second, third: third }; - - expectDeprecation(() => { - bind(root, 'second.input', 'first.output'); - }, /`Ember\.Binding` is deprecated./); - - expectDeprecation(() => { - bind(root, 'second.output', 'third.input'); - }, /`Ember\.Binding` is deprecated./); - }); - } - - afterEach() { - run.cancelTimers(); - } - - ['@test changing first output should propagate to third after flush'](assert) { - run(function() { - set(first, 'output', 'change'); - assert.equal('change', get(first, 'output'), 'first.output'); - assert.ok('change' !== get(third, 'input'), 'third.input'); - }); - - assert.equal('change', get(first, 'output'), 'first.output'); - assert.equal('change', get(second, 'input'), 'second.input'); - assert.equal('change', get(second, 'output'), 'second.output'); - assert.equal('change', get(third, 'input'), 'third.input'); - } -}); - -// .......................................................... -// Custom Binding -// - -moduleFor('Custom Binding', class extends AbstractTestCase { - beforeEach() { - context.lookup = lookup = {}; - - Bon1 = EmberObject.extend({ - value1: 'hi', - value2: 83, - array1: [] - }); - - bon2 = EmberObject.create({ - val1: 'hello', - val2: 25, - arr: [1, 2, 3, 4] - }); - - context.lookup['TestNamespace'] = TestNamespace = { - bon2: bon2, - Bon1: Bon1 - }; - } - afterEach() { - context.lookup = originalLookup; - Bon1 = bon2 = TestNamespace = null; - run.cancelTimers(); - } - - - ['@test two bindings to the same value should sync in the order they are initialized'](assert) { - run.begin(); - - let a = EmberObject.create({ - foo: 'bar' - }); - - let b = EmberObject.extend({ - C: EmberObject.extend({ - foo: 'bee', - fooBinding: 'owner.foo' - }), - - init() { - this._super(...arguments); - set(this, 'c', this.C.create({ owner: this })); - } - }); - - expectDeprecation(() => { - b = b.create({ - foo: 'baz', - fooBinding: 'a.foo', - a: a - }); - }, /`Ember\.Binding` is deprecated./); - - run.end(); - - assert.equal(get(a, 'foo'), 'bar', 'a.foo should not change'); - assert.equal(get(b, 'foo'), 'bar', 'a.foo should propagate up to b.foo'); - assert.equal(get(b.c, 'foo'), 'bar', 'a.foo should propagate up to b.c.foo'); - } -}); - -// .......................................................... -// propertyNameBinding with longhand -// - -moduleFor('propertyNameBinding with longhand', class extends AbstractTestCase { - beforeEach() { - context.lookup = lookup = {}; - - lookup['TestNamespace'] = TestNamespace = {}; - run(() => { - TestNamespace.fromObject = EmberObject.create({ - value: 'originalValue' - }); - - expectDeprecation(() => { - TestNamespace.toObject = EmberObject.extend({ - valueBinding: Binding.from('TestNamespace.fromObject.value'), - relativeBinding: Binding.from('localValue') - }).create({ - localValue: 'originalLocal' - }); - }, /`Ember\.Binding` is deprecated./); - }); - } - - afterEach() { - TestNamespace = undefined; - context.lookup = originalLookup; - } - - ['@test works with full path'](assert) { - run(() => set(TestNamespace.fromObject, 'value', 'updatedValue')); - - assert.equal(get(TestNamespace.toObject, 'value'), 'updatedValue'); - - run(() => set(TestNamespace.fromObject, 'value', 'newerValue')); - - assert.equal(get(TestNamespace.toObject, 'value'), 'newerValue'); - } - - ['@test works with local path'](assert) { - run(() => set(TestNamespace.toObject, 'localValue', 'updatedValue')); - - assert.equal(get(TestNamespace.toObject, 'relative'), 'updatedValue'); - - run(() => set(TestNamespace.toObject, 'localValue', 'newerValue')); - - assert.equal(get(TestNamespace.toObject, 'relative'), 'newerValue'); - } -}); \ No newline at end of file diff --git a/packages/ember-runtime/tests/legacy_1x/system/object/bindings_test.js b/packages/ember-runtime/tests/legacy_1x/system/object/bindings_test.js deleted file mode 100644 index 929e67dc21d..00000000000 --- a/packages/ember-runtime/tests/legacy_1x/system/object/bindings_test.js +++ /dev/null @@ -1,162 +0,0 @@ -import { context } from 'ember-environment'; -import { get, set, run } from 'ember-metal'; -import EmberObject from '../../../../system/object'; -import { moduleFor, AbstractTestCase } from 'internal-test-helpers'; - -/* - NOTE: This test is adapted from the 1.x series of unit tests. The tests - are the same except for places where we intend to break the API we instead - validate that we warn the developer appropriately. - - CHANGES FROM 1.6: - - * changed Ember.Bending.flushPendingChanges() -> run.sync(); - * changes obj.set() and obj.get() to Ember.set() and Ember.get() - * Fixed an actual bug in unit tests around line 133 - * fixed 'bindings should disconnect on destroy' test to use destroy. -*/ - -// ======================================================================== -// EmberObject bindings Tests -// ======================================================================== - -let originalLookup = context.lookup; -let testObject, fromObject, TestObject; -let TestNamespace, lookup; - -moduleFor('bind() method', class extends AbstractTestCase { - beforeEach() { - context.lookup = lookup = {}; - - testObject = EmberObject.create({ - foo: 'bar', - bar: 'foo', - extraObject: null - }); - - fromObject = EmberObject.create({ - bar: 'foo', - extraObject: null - }); - - lookup['TestNamespace'] = TestNamespace = { - fromObject: fromObject, - testObject: testObject - }; - } - - afterEach() { - testObject = fromObject = null; - context.lookup = originalLookup; - } - - ['@test bind(TestNamespace.fromObject.bar) should follow absolute path'](assert) { - run(() => { - expectDeprecation(() => { - // create binding - testObject.bind('foo', 'TestNamespace.fromObject.bar'); - }, /`Ember.Binding` is deprecated/); - - // now make a change to see if the binding triggers. - set(fromObject, 'bar', 'changedValue'); - }); - - assert.equal('changedValue', get(testObject, 'foo'), 'testObject.foo'); - } - - ['@test bind(.bar) should bind to relative path'](assert) { - run(() => { - expectDeprecation(() => { - // create binding - testObject.bind('foo', 'bar'); - }, /`Ember.Binding` is deprecated/); - - // now make a change to see if the binding triggers. - set(testObject, 'bar', 'changedValue'); - }); - - assert.equal('changedValue', get(testObject, 'foo'), 'testObject.foo'); - } -}); - -let deprecationMessage = /`Ember.Binding` is deprecated/; -moduleFor('fooBinding method', class extends AbstractTestCase { - beforeEach() { - context.lookup = lookup = {}; - - TestObject = EmberObject.extend({ - foo: 'bar', - bar: 'foo', - extraObject: null - }); - - fromObject = EmberObject.create({ - bar: 'foo', - extraObject: null - }); - - lookup['TestNamespace'] = TestNamespace = { - fromObject: fromObject, - testObject: TestObject - }; - } - - afterEach() { - context.lookup = originalLookup; - TestObject = fromObject = null; - // delete TestNamespace; - } - - ['@test fooBinding: TestNamespace.fromObject.bar should follow absolute path'](assert) { - run(() => { - expectDeprecation(() => { - // create binding - testObject = TestObject.extend({ - fooBinding: 'TestNamespace.fromObject.bar' - }).create(); - }, deprecationMessage); - - // now make a change to see if the binding triggers. - set(fromObject, 'bar', 'changedValue'); - }); - - assert.equal('changedValue', get(testObject, 'foo'), 'testObject.foo'); - } - - ['@test fooBinding: .bar should bind to relative path'](assert) { - run(() => { - expectDeprecation(() => { - // create binding - testObject = TestObject.extend({ - fooBinding: 'bar' - }).create(); - }, deprecationMessage); - - // now make a change to see if the binding triggers. - set(testObject, 'bar', 'changedValue'); - }); - - assert.equal('changedValue', get(testObject, 'foo'), 'testObject.foo'); - } - - ['@test fooBinding: should disconnect bindings when destroyed'](assert) { - run(() => { - expectDeprecation(() => { - // create binding - testObject = TestObject.extend({ - fooBinding: 'TestNamespace.fromObject.bar' - }).create(); - }, deprecationMessage); - - set(TestNamespace.fromObject, 'bar', 'BAZ'); - }); - - assert.equal(get(testObject, 'foo'), 'BAZ', 'binding should have synced'); - - run(() => testObject.destroy()); - - run(() => set(TestNamespace.fromObject, 'bar', 'BIFF')); - - assert.ok(get(testObject, 'foo') !== 'bar', 'binding should not have synced'); - } -}); \ No newline at end of file diff --git a/packages/ember-runtime/tests/legacy_1x/system/object/concatenated_test.js b/packages/ember-runtime/tests/legacy_1x/system/object/concatenated_test.js index b7bd04ea3ac..93ac62024b1 100644 --- a/packages/ember-runtime/tests/legacy_1x/system/object/concatenated_test.js +++ b/packages/ember-runtime/tests/legacy_1x/system/object/concatenated_test.js @@ -100,4 +100,4 @@ moduleFor('EmberObject Concatenated Properties', class extends AbstractTestCase assert.deepEqual(values, expected, `should concatenate functions property (expected: ${expected}, got: ${values})`); } -}); \ No newline at end of file +}); diff --git a/packages/ember-runtime/tests/legacy_1x/system/run_loop_test.js b/packages/ember-runtime/tests/legacy_1x/system/run_loop_test.js deleted file mode 100644 index aff1d92ed4a..00000000000 --- a/packages/ember-runtime/tests/legacy_1x/system/run_loop_test.js +++ /dev/null @@ -1,116 +0,0 @@ -import { - observer as emberObserver, - run, - Binding -} from 'ember-metal'; -import Observable from '../../../mixins/observable'; -import EmberObject from '../../../system/object'; -import { moduleFor, AbstractTestCase } from 'internal-test-helpers'; - -/* - NOTE: This test is adapted from the 1.x series of unit tests. The tests - are the same except for places where we intend to break the API we instead - validate that we warn the developer appropriately. - - CHANGES FROM 1.6: - - * Updated the API usage for setting up and syncing Binding since these - are not the APIs this file is testing. - - * Disabled a call to invokeOnce() around line 127 because it appeared to be - broken anyway. I don't think it ever even worked. -*/ - -let MyApp; -let deprecationMessage = /`Ember.Binding` is deprecated/; - -moduleFor('System:run_loop() - chained binding', class extends AbstractTestCase { - beforeEach() { - MyApp = {}; - MyApp.first = EmberObject.extend(Observable).create({ - output: 'MyApp.first' - }); - - MyApp.second = EmberObject.extend(Observable, { - inputDidChange: emberObserver('input', function() { - this.set('output', this.get('input')); - }) - }).create({ - input: 'MyApp.second', - output: 'MyApp.second' - }); - - MyApp.third = EmberObject.extend(Observable).create({ - input: 'MyApp.third' - }); - } - - ['@test Should propagate bindings after the RunLoop completes (using Ember.RunLoop)'](assert) { - run(() => { - //Binding of output of MyApp.first object to input of MyApp.second object - expectDeprecation(() => { - Binding.from('first.output') - .to('second.input').connect(MyApp); - }, deprecationMessage); - - //Binding of output of MyApp.second object to input of MyApp.third object - expectDeprecation(() => { - Binding.from('second.output') - .to('third.input').connect(MyApp); - }, deprecationMessage); - }); - - run(() => { - // Based on the above binding if you change the output of MyApp.first - // object it should change the all the variable of - // MyApp.first,MyApp.second and MyApp.third object - MyApp.first.set('output', 'change'); - - //Changes the output of the MyApp.first object - assert.equal(MyApp.first.get('output'), 'change'); - - //since binding has not taken into effect the value still remains as change. - assert.equal(MyApp.second.get('output'), 'MyApp.first'); - }); // allows bindings to trigger... - - //Value of the output variable changed to 'change' - assert.equal(MyApp.first.get('output'), 'change'); - - //Since binding triggered after the end loop the value changed to 'change'. - assert.equal(MyApp.second.get('output'), 'change'); - } - - ['@test Should propagate bindings after the RunLoop completes'](assert) { - run(() => { - //Binding of output of MyApp.first object to input of MyApp.second object - expectDeprecation(() => { - Binding.from('first.output') - .to('second.input').connect(MyApp); - }, deprecationMessage); - - //Binding of output of MyApp.second object to input of MyApp.third object - expectDeprecation(() => { - Binding.from('second.output') - .to('third.input').connect(MyApp); - }, deprecationMessage); - }); - - run(() => { - //Based on the above binding if you change the output of MyApp.first object it should - //change the all the variable of MyApp.first,MyApp.second and MyApp.third object - MyApp.first.set('output', 'change'); - - //Changes the output of the MyApp.first object - assert.equal(MyApp.first.get('output'), 'change'); - - //since binding has not taken into effect the value still remains as change. - assert.equal(MyApp.second.get('output'), 'MyApp.first'); - }); - - //Value of the output variable changed to 'change' - assert.equal(MyApp.first.get('output'), 'change'); - - //Since binding triggered after the end loop the value changed to 'change'. - assert.equal(MyApp.second.get('output'), 'change'); - } -}); \ No newline at end of file diff --git a/packages/ember-runtime/tests/system/object/create_test.js b/packages/ember-runtime/tests/system/object/create_test.js index bef6cc61f2f..284bb4a938c 100644 --- a/packages/ember-runtime/tests/system/object/create_test.js +++ b/packages/ember-runtime/tests/system/object/create_test.js @@ -1,5 +1,4 @@ import { - meta, computed, Mixin, observer @@ -49,21 +48,6 @@ if (MANDATORY_SETTER) { }); } -QUnit.test('allows bindings to be defined', function(assert) { - let obj; - - let deprecationMessage = /`Ember.Binding` is deprecated/; - - expectDeprecation(() => { - obj = EmberObject.create({ - foo: 'foo', - barBinding: 'foo' - }); - }, deprecationMessage); - - assert.equal(obj.get('bar'), 'foo', 'The binding value is correct'); -}); - QUnit.test('calls setUnknownProperty if defined', function(assert) { let setUnknownPropertyCalled = false; @@ -129,9 +113,3 @@ QUnit.test('EmberObject.create can take null as a parameter', function(assert) { let o = EmberObject.create(null); assert.deepEqual(EmberObject.create(), o); }); - -QUnit.test('EmberObject.create avoids allocating a binding map when not necessary', function(assert) { - let o = EmberObject.create(); - let m = meta(o); - assert.ok(!m.peekBindings(), 'A binding map is not allocated'); -}); diff --git a/packages/ember-runtime/tests/system/object/destroy_test.js b/packages/ember-runtime/tests/system/object/destroy_test.js index 7b58b0f744b..1d0a69773ef 100644 --- a/packages/ember-runtime/tests/system/object/destroy_test.js +++ b/packages/ember-runtime/tests/system/object/destroy_test.js @@ -2,7 +2,6 @@ import { run, observer, set, - bind, beginPropertyChanges, endPropertyChanges, peekMeta @@ -141,31 +140,3 @@ QUnit.test('destroyed objects should not see each others changes during teardown assert.equal(shouldNotChange, 0, 'destroyed graph objs should not see change in willDestroy'); assert.equal(shouldChange, 1, 'long lived should see change in willDestroy'); }); - -QUnit.test('bindings should be synced when are updated in the willDestroy hook', function(assert) { - let bar = EmberObject.create({ - value: false, - willDestroy() { - this.set('value', true); - } - }); - - let foo = EmberObject.create({ - value: null, - bar: bar - }); - - run(() => { - let deprecationMessage = /`Ember.Binding` is deprecated/; - - expectDeprecation(() => { - bind(foo, 'value', 'bar.value'); - }, deprecationMessage); - }); - - assert.ok(bar.get('value') === false, 'the initial value has been bound'); - - run(() => bar.destroy()); - - assert.ok(foo.get('value'), 'foo is synced when the binding is updated in the willDestroy hook'); -}); diff --git a/packages/ember-runtime/tests/system/object/subclasses_test.js b/packages/ember-runtime/tests/system/object/subclasses_test.js deleted file mode 100644 index cc02de5d36f..00000000000 --- a/packages/ember-runtime/tests/system/object/subclasses_test.js +++ /dev/null @@ -1,44 +0,0 @@ -import { run, computed } from 'ember-metal'; -import EmberObject from '../../../system/object'; - -QUnit.module('system/object/subclasses'); - -QUnit.test('chains should copy forward to subclasses when prototype created', function(assert) { - let ObjectWithChains, objWithChains, SubWithChains, SubSub, subSub; - run(() => { - ObjectWithChains = EmberObject.extend({ - obj: { - a: 'a', - hi: 'hi' - }, - aBinding: 'obj.a' // add chain - }); - - - let deprecationMessage = /`Ember.Binding` is deprecated/; - - expectDeprecation(() => { - // realize prototype - objWithChains = ObjectWithChains.create(); - }, deprecationMessage); - - // should not copy chains from parent yet - SubWithChains = ObjectWithChains.extend({ - hiBinding: 'obj.hi', // add chain - hello: computed(function() { - return this.get('obj.hi') + ' world'; - }).property('hi'), // observe chain - greetingBinding: 'hello' - }); - - SubSub = SubWithChains.extend(); - - expectDeprecation(() => { - // should realize prototypes and copy forward chains - subSub = SubSub.create(); - }, deprecationMessage); - }); - assert.equal(subSub.get('greeting'), 'hi world'); - run(() => objWithChains.set('obj.hi', 'hello')); - assert.equal(subSub.get('greeting'), 'hello world'); -}); diff --git a/packages/ember/tests/reexports_test.js b/packages/ember/tests/reexports_test.js index 8e4a9a98145..824862d47d4 100644 --- a/packages/ember/tests/reexports_test.js +++ b/packages/ember/tests/reexports_test.js @@ -113,8 +113,6 @@ let allExports =[ ['observer', 'ember-metal'], ['mixin', 'ember-metal'], ['Mixin', 'ember-metal'], - ['bind', 'ember-metal'], - ['Binding', 'ember-metal'], ['isGlobalPath', 'ember-metal'], // ember-views