From 4ccc32f067a1ca3084de0c60ee778ced7651bc7f Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Sat, 18 Apr 2015 11:13:54 -0700 Subject: [PATCH 01/12] Internals should prefer generic array methods over prototype_extensions --- .../ember-extension-support/lib/data_adapter.js | 16 +++++++--------- .../lib/computed/reduce_computed.js | 6 ++++-- packages/ember-runtime/lib/mixins/array.js | 9 +++++++++ packages/ember-runtime/lib/system/array_proxy.js | 12 ++++++++---- packages/ember-runtime/lib/system/each_proxy.js | 10 +++++----- .../controllers/item_controller_class_test.js | 8 ++++++-- .../ember-runtime/tests/mixins/array_test.js | 6 ++++-- packages/ember-runtime/tests/suites/array.js | 8 ++++++-- .../ember-views/lib/views/collection_view.js | 6 ++++-- 9 files changed, 53 insertions(+), 28 deletions(-) diff --git a/packages/ember-extension-support/lib/data_adapter.js b/packages/ember-extension-support/lib/data_adapter.js index 7d41666cc03..2065c8e6bd8 100644 --- a/packages/ember-extension-support/lib/data_adapter.js +++ b/packages/ember-extension-support/lib/data_adapter.js @@ -5,7 +5,7 @@ import Namespace from 'ember-runtime/system/namespace'; import EmberObject from 'ember-runtime/system/object'; import { A as emberA } from 'ember-runtime/system/native_array'; import Application from 'ember-application/system/application'; - +import { addArrayObserver } from 'ember-runtime/mixins/array'; /** @module ember @submodule ember-extension-support @@ -40,7 +40,7 @@ import Application from 'ember-application/system/application'; ```javascript Application.initializer({ - name: "data-adapter", + name: 'data-adapter', initialize: function(container, application) { application.register('data-adapter:main', DS.DataAdapter); @@ -162,7 +162,7 @@ export default EmberObject.extend({ typesAdded(typesToSend); var release = () => { - releaseMethods.forEach((fn) => fn() ); + releaseMethods.forEach(fn => fn()); this.releaseMethods.removeObject(release); }; this.releaseMethods.pushObject(release); @@ -230,10 +230,10 @@ export default EmberObject.extend({ }; var observer = { didChange: contentDidChange, willChange() { return this; } }; - records.addArrayObserver(this, observer); + addArrayObserver(records, this, observer); release = () => { - releaseMethods.forEach(function(fn) { fn(); }); + releaseMethods.forEach(fn => fn()); records.removeArrayObserver(this, observer); this.releaseMethods.removeObject(release); }; @@ -251,9 +251,7 @@ export default EmberObject.extend({ */ willDestroy() { this._super(...arguments); - this.releaseMethods.forEach(function(fn) { - fn(); - }); + this.releaseMethods.forEach(fn => fn()); }, /** @@ -309,7 +307,7 @@ export default EmberObject.extend({ willChange() { return this; } }; - records.addArrayObserver(this, observer); + addArrayObserver(records, this, observer); var release = () => { records.removeArrayObserver(this, observer); diff --git a/packages/ember-runtime/lib/computed/reduce_computed.js b/packages/ember-runtime/lib/computed/reduce_computed.js index a84adb1530e..22a08780088 100644 --- a/packages/ember-runtime/lib/computed/reduce_computed.js +++ b/packages/ember-runtime/lib/computed/reduce_computed.js @@ -21,7 +21,9 @@ import { cacheFor } from 'ember-metal/computed'; import TrackedArray from 'ember-runtime/system/tracked_array'; -import EmberArray from 'ember-runtime/mixins/array'; +import EmberArray, { + addArrayObserver +} from 'ember-runtime/mixins/array'; import run from 'ember-metal/run_loop'; var cacheSet = cacheFor.set; @@ -107,7 +109,7 @@ DependentArraysObserver.prototype = { setupObservers(dependentArray, dependentKey) { this.dependentKeysByGuid[guidFor(dependentArray)] = dependentKey; - dependentArray.addArrayObserver(this, { + addArrayObserver(dependentArray, this, { willChange: 'dependentArrayWillChange', didChange: 'dependentArrayDidChange' }); diff --git a/packages/ember-runtime/lib/mixins/array.js b/packages/ember-runtime/lib/mixins/array.js index 297cdfc975c..1db9eeee9b0 100644 --- a/packages/ember-runtime/lib/mixins/array.js +++ b/packages/ember-runtime/lib/mixins/array.js @@ -47,6 +47,15 @@ function arrayObserversHelper(obj, target, opts, operation, notify) { return obj; } +export function addArrayObserver(array, target, opts) { + return arrayObserversHelper(array, target, opts, addListener, false); +} + +export function removeArrayObserver(array, target, opts) { + return arrayObserversHelper(array, target, opts, removeListener, true); +} + + // .......................................................... // ARRAY // diff --git a/packages/ember-runtime/lib/system/array_proxy.js b/packages/ember-runtime/lib/system/array_proxy.js index 94d38deb33b..ce35798857e 100644 --- a/packages/ember-runtime/lib/system/array_proxy.js +++ b/packages/ember-runtime/lib/system/array_proxy.js @@ -18,6 +18,10 @@ import MutableArray from 'ember-runtime/mixins/mutable_array'; import Enumerable from 'ember-runtime/mixins/enumerable'; import { fmt } from 'ember-runtime/system/string'; import alias from 'ember-metal/alias'; +import { + addArrayObserver, + removeArrayObserver +} from 'ember-runtime/mixins/array'; /** @module ember @@ -140,7 +144,7 @@ var ArrayProxy = EmberObject.extend(MutableArray, { var content = get(this, 'content'); if (content) { - content.removeArrayObserver(this, { + removeArrayObserver(content, this, { willChange: 'contentArrayWillChange', didChange: 'contentArrayDidChange' }); @@ -195,7 +199,7 @@ var ArrayProxy = EmberObject.extend(MutableArray, { 'Ember.ArrayProxy, but you passed %@', [typeof content]), isArray(content) || content.isDestroyed); - content.addArrayObserver(this, { + addArrayObserver(content, this, { willChange: 'contentArrayWillChange', didChange: 'contentArrayDidChange' }); @@ -232,7 +236,7 @@ var ArrayProxy = EmberObject.extend(MutableArray, { 'Ember.ArrayProxy, but you passed %@', [typeof arrangedContent]), isArray(arrangedContent) || arrangedContent.isDestroyed); - arrangedContent.addArrayObserver(this, { + addArrayObserver(arrangedContent, this, { willChange: 'arrangedContentArrayWillChange', didChange: 'arrangedContentArrayDidChange' }); @@ -243,7 +247,7 @@ var ArrayProxy = EmberObject.extend(MutableArray, { var arrangedContent = get(this, 'arrangedContent'); if (arrangedContent) { - arrangedContent.removeArrayObserver(this, { + removeArrayObserver(arrangedContent, this, { willChange: 'arrangedContentArrayWillChange', didChange: 'arrangedContentArrayDidChange' }); diff --git a/packages/ember-runtime/lib/system/each_proxy.js b/packages/ember-runtime/lib/system/each_proxy.js index b5c74c7584c..538159e28cd 100644 --- a/packages/ember-runtime/lib/system/each_proxy.js +++ b/packages/ember-runtime/lib/system/each_proxy.js @@ -8,9 +8,11 @@ import Ember from 'ember-metal/core'; // Ember.assert import { get } from 'ember-metal/property_get'; import { guidFor } from 'ember-metal/utils'; import { typeOf } from 'ember-runtime/utils'; -import EmberArray from 'ember-runtime/mixins/array'; // ES6TODO: WAT? Circular dep? import EmberObject from 'ember-runtime/system/object'; import { computed } from 'ember-metal/computed'; +import EmberArray, { + addArrayObserver +} from 'ember-runtime/mixins/array'; // ES6TODO: WAT? Circular dep? import { addObserver, addBeforeObserver, @@ -109,13 +111,11 @@ var EachProxy = EmberObject.extend({ init(content) { this._super(...arguments); this._content = content; - content.addArrayObserver(this); + addArrayObserver(content, this); // in case someone is already observing some keys make sure they are // added - watchedEvents(this).forEach((eventName) => { - this.didAddListener(eventName); - }); + watchedEvents(this).forEach(eventName => this.didAddListener(eventName)); }, /** diff --git a/packages/ember-runtime/tests/controllers/item_controller_class_test.js b/packages/ember-runtime/tests/controllers/item_controller_class_test.js index 2d8738474f5..f12cee35b88 100644 --- a/packages/ember-runtime/tests/controllers/item_controller_class_test.js +++ b/packages/ember-runtime/tests/controllers/item_controller_class_test.js @@ -9,6 +9,9 @@ import ArrayController, { arrayControllerDeprecation } from 'ember-runtime/contr import Controller from 'ember-runtime/controllers/controller'; import {sort} from 'ember-runtime/computed/reduce_computed_macros'; import Registry from 'container/registry'; +import { + addArrayObserver +} from 'ember-runtime/mixins/array'; var lannisters, arrayController, controllerClass, otherControllerClass, registry, container, itemControllerCount, tywin, jaime, cersei, tyrion; @@ -314,12 +317,13 @@ QUnit.test('array observers can invoke `objectAt` without overwriting existing i equal(this.objectAt(idx).get('model.name'), 'Tyrion', 'Array observers get the right object via `objectAt`'); } }); - arrayController.addArrayObserver(arrayController, { + + addArrayObserver(arrayController, arrayController, { willChange: 'lannistersWillChange', didChange: 'lannistersDidChange' }); - run(function() { + run(() => { lannisters.unshiftObject(tyrion); }); diff --git a/packages/ember-runtime/tests/mixins/array_test.js b/packages/ember-runtime/tests/mixins/array_test.js index 23fa9bbbe8a..777931b1bfe 100644 --- a/packages/ember-runtime/tests/mixins/array_test.js +++ b/packages/ember-runtime/tests/mixins/array_test.js @@ -7,7 +7,9 @@ import { computed } from 'ember-metal/computed'; import { testBoth } from 'ember-metal/tests/props_helper'; import { ArrayTests } from 'ember-runtime/tests/suites/array'; import EmberObject from 'ember-runtime/system/object'; -import EmberArray from 'ember-runtime/mixins/array'; +import EmberArray, { + addArrayObserver +} from 'ember-runtime/mixins/array'; /* Implement a basic fake mutable array. This validates that any non-native @@ -202,7 +204,7 @@ QUnit.module('notify array observers', { _after: null }); - obj.addArrayObserver(observer); + addArrayObserver(obj, observer); }, teardown() { diff --git a/packages/ember-runtime/tests/suites/array.js b/packages/ember-runtime/tests/suites/array.js index 0a1528567ce..dab019c247b 100644 --- a/packages/ember-runtime/tests/suites/array.js +++ b/packages/ember-runtime/tests/suites/array.js @@ -5,16 +5,20 @@ import { import indexOfTests from 'ember-runtime/tests/suites/array/indexOf'; import lastIndexOfTests from 'ember-runtime/tests/suites/array/lastIndexOf'; import objectAtTests from 'ember-runtime/tests/suites/array/objectAt'; +import { + addArrayObserver, + removeArrayObserver +} from 'ember-runtime/mixins/array'; var ObserverClass = EnumerableTestsObserverClass.extend({ observeArray(obj) { - obj.addArrayObserver(this); + addArrayObserver(obj, this); return this; }, stopObserveArray(obj) { - obj.removeArrayObserver(this); + removeArrayObserver(obj, this); return this; }, diff --git a/packages/ember-views/lib/views/collection_view.js b/packages/ember-views/lib/views/collection_view.js index 4061f447cbc..0fffd8a72d3 100644 --- a/packages/ember-views/lib/views/collection_view.js +++ b/packages/ember-views/lib/views/collection_view.js @@ -6,7 +6,9 @@ import Ember from 'ember-metal/core'; // Ember.assert import ContainerView from 'ember-views/views/container_view'; import View from 'ember-views/views/view'; -import EmberArray from 'ember-runtime/mixins/array'; +import EmberArray, { + addArrayObserver +} from 'ember-runtime/mixins/array'; import { get } from 'ember-metal/property_get'; import { set } from 'ember-metal/property_set'; import { fmt } from 'ember-runtime/system/string'; @@ -244,7 +246,7 @@ var CollectionView = ContainerView.extend(EmptyViewSupport, { if (content) { this._assertArrayLike(content); - content.addArrayObserver(this); + addArrayObserver(content, this); } var len = content ? get(content, 'length') : 0; From 2245ad2e29f331f8f7291d92a47c89ae91037683 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Sat, 18 Apr 2015 12:53:55 -0700 Subject: [PATCH 02/12] prefer generic objectAt over potential prototype extension variant --- .../lib/data_adapter.js | 7 +++- .../tests/helpers/collection_test.js | 6 +-- .../ember-htmlbars/tests/helpers/view_test.js | 6 ++- .../lib/computed/reduce_computed.js | 7 ++-- .../lib/computed/reduce_computed_macros.js | 3 +- .../lib/controllers/array_controller.js | 6 ++- packages/ember-runtime/lib/mixins/array.js | 13 +++--- packages/ember-runtime/lib/mixins/sortable.js | 14 +++++-- .../ember-runtime/lib/system/array_proxy.js | 13 ++++-- .../ember-runtime/lib/system/each_proxy.js | 9 +++-- .../computed/reduce_computed_macros_test.js | 40 ++++++++++--------- .../tests/computed/reduce_computed_test.js | 15 +++---- .../controllers/item_controller_class_test.js | 5 ++- .../ember-runtime/tests/mixins/array_test.js | 13 +++--- .../tests/mixins/sortable_test.js | 3 +- .../tests/suites/array/objectAt.js | 6 +-- .../array_proxy/arranged_content_test.js | 7 ++-- .../ember-views/lib/views/collection_view.js | 5 ++- packages/ember-views/lib/views/select.js | 3 +- .../tests/views/view/destroy_element_test.js | 3 +- .../tests/views/view/element_test.js | 3 +- .../tests/views/view/is_visible_test.js | 5 ++- .../tests/views/view/remove_test.js | 7 ++-- 23 files changed, 117 insertions(+), 82 deletions(-) diff --git a/packages/ember-extension-support/lib/data_adapter.js b/packages/ember-extension-support/lib/data_adapter.js index 2065c8e6bd8..d71fd4b38a5 100644 --- a/packages/ember-extension-support/lib/data_adapter.js +++ b/packages/ember-extension-support/lib/data_adapter.js @@ -5,7 +5,10 @@ import Namespace from 'ember-runtime/system/namespace'; import EmberObject from 'ember-runtime/system/object'; import { A as emberA } from 'ember-runtime/system/native_array'; import Application from 'ember-application/system/application'; -import { addArrayObserver } from 'ember-runtime/mixins/array'; +import { + addArrayObserver, + objectAt +} from 'ember-runtime/mixins/array'; /** @module ember @submodule ember-extension-support @@ -218,7 +221,7 @@ export default EmberObject.extend({ var contentDidChange = (array, idx, removedCount, addedCount) => { for (var i = idx; i < idx + addedCount; i++) { - var record = array.objectAt(i); + var record = objectAt(array, i); var wrapped = this.wrapRecord(record); releaseMethods.push(this.observeRecord(record, recordUpdated)); recordsAdded([wrapped]); diff --git a/packages/ember-htmlbars/tests/helpers/collection_test.js b/packages/ember-htmlbars/tests/helpers/collection_test.js index ccfae95dc2f..5f3e5e1cab4 100644 --- a/packages/ember-htmlbars/tests/helpers/collection_test.js +++ b/packages/ember-htmlbars/tests/helpers/collection_test.js @@ -14,10 +14,10 @@ import CollectionView from 'ember-views/views/collection_view'; import EmberView from 'ember-views/views/view'; import jQuery from 'ember-views/system/jquery'; import compile from 'ember-template-compiler/system/compile'; +import { objectAt } from 'ember-runtime/mixins/array'; var trim = jQuery.trim; - var view; var originalLookup = Ember.lookup; @@ -25,13 +25,13 @@ var TemplateTests, registry, container, lookup; function nthChild(view, nth) { - return get(view, 'childViews').objectAt(nth || 0); + return objectAt(get(view, 'childViews'), nth || 0); } var firstChild = nthChild; function firstGrandchild(view) { - return get(get(view, 'childViews').objectAt(0), 'childViews').objectAt(0); + return objectAt(get(objectAt(get(view, 'childViews'), 0), 'childViews'), 0); } QUnit.module('collection helper', { diff --git a/packages/ember-htmlbars/tests/helpers/view_test.js b/packages/ember-htmlbars/tests/helpers/view_test.js index add0f99297b..d1733e47edb 100644 --- a/packages/ember-htmlbars/tests/helpers/view_test.js +++ b/packages/ember-htmlbars/tests/helpers/view_test.js @@ -23,16 +23,18 @@ import { set } from 'ember-metal/property_set'; import { get } from 'ember-metal/property_get'; import { computed } from 'ember-metal/computed'; +import { objectAt } from 'ember-runtime/mixins/array'; + var view, originalLookup, registry, container, lookup; var trim = jQuery.trim; function firstGrandchild(view) { - return get(get(view, 'childViews').objectAt(0), 'childViews').objectAt(0); + return objectAt(get(objectAt(get(view, 'childViews'), 0), 'childViews'), 0); } function nthChild(view, nth) { - return get(view, 'childViews').objectAt(nth || 0); + return objectAt(get(view, 'childViews'), nth || 0); } function viewClass(options) { diff --git a/packages/ember-runtime/lib/computed/reduce_computed.js b/packages/ember-runtime/lib/computed/reduce_computed.js index 22a08780088..5736195a1a6 100644 --- a/packages/ember-runtime/lib/computed/reduce_computed.js +++ b/packages/ember-runtime/lib/computed/reduce_computed.js @@ -22,7 +22,8 @@ import { } from 'ember-metal/computed'; import TrackedArray from 'ember-runtime/system/tracked_array'; import EmberArray, { - addArrayObserver + addArrayObserver, + objectAt } from 'ember-runtime/mixins/array'; import run from 'ember-metal/run_loop'; @@ -90,7 +91,7 @@ function ItemPropertyObserverContext(dependentArray, index, trackedArray) { this.dependentArray = dependentArray; this.index = index; - this.item = dependentArray.objectAt(index); + this.item = objectAt(dependentArray, index); this.trackedArray = trackedArray; this.beforeObserver = null; this.observer = null; @@ -268,7 +269,7 @@ DependentArraysObserver.prototype = { itemIndex = normalizedIndex + sliceIndex; if (itemIndex >= length) { break; } - item = dependentArray.objectAt(itemIndex); + item = objectAt(dependentArray, itemIndex); itemPropertyKeys.forEach(removeObservers, this); diff --git a/packages/ember-runtime/lib/computed/reduce_computed_macros.js b/packages/ember-runtime/lib/computed/reduce_computed_macros.js index 755669f0f0b..7220cd1ca66 100644 --- a/packages/ember-runtime/lib/computed/reduce_computed_macros.js +++ b/packages/ember-runtime/lib/computed/reduce_computed_macros.js @@ -15,6 +15,7 @@ import { arrayComputed } from 'ember-runtime/computed/array_computed'; import { reduceComputed } from 'ember-runtime/computed/reduce_computed'; import SubArray from 'ember-runtime/system/subarray'; import compare from 'ember-runtime/compare'; +import { objectAt } from 'ember-runtime/mixins/array'; var a_slice = [].slice; @@ -625,7 +626,7 @@ function binarySearch(array, item, low, high) { } mid = low + Math.floor((high - low) / 2); - midItem = array.objectAt(mid); + midItem = objectAt(array, mid); guidMid = guidFor(midItem); guidItem = guidFor(item); diff --git a/packages/ember-runtime/lib/controllers/array_controller.js b/packages/ember-runtime/lib/controllers/array_controller.js index 9385f5439e0..3589fc376b2 100644 --- a/packages/ember-runtime/lib/controllers/array_controller.js +++ b/packages/ember-runtime/lib/controllers/array_controller.js @@ -10,8 +10,10 @@ import SortableMixin from 'ember-runtime/mixins/sortable'; import ControllerMixin from 'ember-runtime/mixins/controller'; import { computed } from 'ember-metal/computed'; import EmberError from 'ember-metal/error'; -import EmberArray from 'ember-runtime/mixins/array'; import replace from 'ember-metal/replace'; +import EmberArray, { + objectAt +} from 'ember-runtime/mixins/array'; export var arrayControllerDeprecation = '`Ember.ArrayController` is deprecated.'; @@ -155,7 +157,7 @@ export default ArrayProxy.extend(ControllerMixin, SortableMixin, { objectAtContent(idx) { var length = get(this, 'length'); var arrangedContent = get(this, 'arrangedContent'); - var object = arrangedContent && arrangedContent.objectAt(idx); + var object = arrangedContent && objectAt(arrangedContent, idx); var controllerClass; if (idx >= 0 && idx < length) { diff --git a/packages/ember-runtime/lib/mixins/array.js b/packages/ember-runtime/lib/mixins/array.js index 1db9eeee9b0..661a5ecd3d5 100644 --- a/packages/ember-runtime/lib/mixins/array.js +++ b/packages/ember-runtime/lib/mixins/array.js @@ -55,6 +55,11 @@ export function removeArrayObserver(array, target, opts) { return arrayObserversHelper(array, target, opts, removeListener, true); } +export function objectAt(content, idx) { + if (content.objectAt) { return content.objectAt(idx); } + return content[idx]; +} + // .......................................................... // ARRAY @@ -157,16 +162,12 @@ export default Mixin.create(Enumerable, { @public */ objectsAt(indexes) { - var self = this; - - return indexes.map(function(idx) { - return self.objectAt(idx); - }); + return indexes.map(idx => objectAt(this, idx)); }, // overrides Ember.Enumerable version nextObject(idx) { - return this.objectAt(idx); + return objectAt(this, idx); }, /** diff --git a/packages/ember-runtime/lib/mixins/sortable.js b/packages/ember-runtime/lib/mixins/sortable.js index 624f94a180c..eebcccaaaa3 100644 --- a/packages/ember-runtime/lib/mixins/sortable.js +++ b/packages/ember-runtime/lib/mixins/sortable.js @@ -19,7 +19,13 @@ import { beforeObserver, observer } from 'ember-metal/mixin'; //ES6TODO: should we access these directly from their package or from how their exposed in ember-metal? +import { + objectAt +} from 'ember-runtime/mixins/array'; +import { + indexOf +} from 'ember-metal/enumerable_utils'; /** `Ember.SortableMixin` provides a standard interface for array proxies to specify a sort order and maintain this sorting when objects are added, @@ -271,9 +277,9 @@ export default Mixin.create(MutableEnumerable, { contentItemSortPropertyDidChange(item) { var arrangedContent = get(this, 'arrangedContent'); - var oldIndex = arrangedContent.indexOf(item); - var leftItem = arrangedContent.objectAt(oldIndex - 1); - var rightItem = arrangedContent.objectAt(oldIndex + 1); + var oldIndex = indexOf(arrangedContent, item); + var leftItem = objectAt(arrangedContent, oldIndex - 1); + var rightItem = objectAt(arrangedContent, oldIndex + 1); var leftResult = leftItem && this.orderBy(item, leftItem); var rightResult = rightItem && this.orderBy(item, rightItem); @@ -293,7 +299,7 @@ export default Mixin.create(MutableEnumerable, { arrangedContent = get(this, 'arrangedContent'); mid = low + Math.floor((high - low) / 2); - midItem = arrangedContent.objectAt(mid); + midItem = objectAt(arrangedContent, mid); res = this.orderBy(midItem, item); diff --git a/packages/ember-runtime/lib/system/array_proxy.js b/packages/ember-runtime/lib/system/array_proxy.js index ce35798857e..4f52ac020de 100644 --- a/packages/ember-runtime/lib/system/array_proxy.js +++ b/packages/ember-runtime/lib/system/array_proxy.js @@ -20,8 +20,13 @@ import { fmt } from 'ember-runtime/system/string'; import alias from 'ember-metal/alias'; import { addArrayObserver, - removeArrayObserver -} from 'ember-runtime/mixins/array'; + removeArrayObserver, + objectAt +} from "ember-runtime/mixins/array"; + +import { + indexOf +} from "ember-metal/enumerable_utils"; /** @module ember @@ -107,7 +112,7 @@ var ArrayProxy = EmberObject.extend(MutableArray, { @private */ objectAtContent(idx) { - return get(this, 'arrangedContent').objectAt(idx); + return objectAt(get(this, 'arrangedContent'), idx); }, /** @@ -320,7 +325,7 @@ var ArrayProxy = EmberObject.extend(MutableArray, { // Get a list of indices in original content to remove for (i=start; i= idx) { - var item = content.objectAt(loc); + var item = objectAt(content, loc); if (item) { Ember.assert('When using @each to observe the array ' + content + ', the array must return an object', typeOf(item) === 'instance' || typeOf(item) === 'object'); addBeforeObserver(item, keyName, proxy, 'contentKeyWillChange'); @@ -87,7 +88,7 @@ function removeObserverForContentKey(content, keyName, proxy, idx, loc) { var indices, guid; while (--loc >= idx) { - var item = content.objectAt(loc); + var item = objectAt(content, loc); if (item) { removeBeforeObserver(item, keyName, proxy, 'contentKeyWillChange'); removeObserver(item, keyName, proxy, 'contentKeyDidChange'); diff --git a/packages/ember-runtime/tests/computed/reduce_computed_macros_test.js b/packages/ember-runtime/tests/computed/reduce_computed_macros_test.js index 48c9232ff1c..a4a21f81604 100644 --- a/packages/ember-runtime/tests/computed/reduce_computed_macros_test.js +++ b/packages/ember-runtime/tests/computed/reduce_computed_macros_test.js @@ -26,6 +26,8 @@ import { intersect as computedIntersect } from 'ember-runtime/computed/reduce_computed_macros'; +import { objectAt } from 'ember-runtime/mixins/array'; + var obj, sorted, sortProps, items, userFnCalls, todos, filtered, union; QUnit.module('computedMap', { @@ -146,7 +148,7 @@ QUnit.test('it maps objects', function() { deepEqual(get(obj, 'mappedObjects'), [{ name: 'Robert' }, { name: 'Eddard' }]); run(function() { - obj.get('arrayObjects').objectAt(0).set('v', { name: 'Stannis' }); + objectAt(obj.get('arrayObjects'), 0).set('v', { name: 'Stannis' }); }); deepEqual(get(obj, 'mappedObjects'), [{ name: 'Stannis' }, { name: 'Eddard' }]); @@ -413,11 +415,11 @@ QUnit.test('properties can be filtered by truthiness', function() { deepEqual(bs.mapBy('name'), ['three', 'four'], 'booleans can be filtered'); run(function() { - set(array.objectAt(0), 'a', undefined); - set(array.objectAt(3), 'a', true); + set(objectAt(array, 0), 'a', undefined); + set(objectAt(array, 3), 'a', true); - set(array.objectAt(0), 'b', true); - set(array.objectAt(3), 'b', false); + set(objectAt(array, 0), 'b', true); + set(objectAt(array, 3), 'b', false); }); deepEqual(as.mapBy('name'), ['two', 'three', 'four'], 'arrays computed by filter property respond to property changes'); deepEqual(bs.mapBy('name'), ['one', 'three'], 'arrays computed by filtered property respond to property changes'); @@ -458,8 +460,8 @@ QUnit.test('properties can be filtered by values', function() { deepEqual(a1s.mapBy('name'), ['one', 'three'], 'arrays computed by matching value respond to removed objects'); run(function() { - set(array.objectAt(1), 'a', 1); - set(array.objectAt(2), 'a', 2); + set(objectAt(array, 1), 'a', 1); + set(objectAt(array, 2), 'a', 2); }); deepEqual(a1s.mapBy('name'), ['one', 'two'], 'arrays computed by matching value respond to modified properties'); }); @@ -932,7 +934,7 @@ QUnit.test('updating new sort properties in place updates the sorted array', fun run(function() { items = get(obj, 'items'); - var cersei = items.objectAt(1); + var cersei = objectAt(items, 1); set(cersei, 'age', 29); // how vain }); @@ -961,7 +963,7 @@ QUnit.test('updating an item\'s sort properties updates the sorted array', funct items = get(obj, 'items'); }); - tyrionInDisguise = items.objectAt(1); + tyrionInDisguise = objectAt(items, 1); deepEqual(sorted.mapBy('fname'), ['Cersei', 'Jaime', 'Bran', 'Robb'], 'precond - array is initially sorted'); @@ -980,7 +982,7 @@ QUnit.test('updating several of an item\'s sort properties updated the sorted ar items = get(obj, 'items'); }); - sansaInDisguise = items.objectAt(1); + sansaInDisguise = objectAt(items, 1); deepEqual(sorted.mapBy('fname'), ['Cersei', 'Jaime', 'Bran', 'Robb'], 'precond - array is initially sorted'); @@ -1176,7 +1178,7 @@ QUnit.test('changing item properties specified via @each triggers a resort of th items = get(obj, 'items'); }); - tyrionInDisguise = items.objectAt(1); + tyrionInDisguise = objectAt(items, 1); deepEqual(sorted.mapBy('fname'), ['Cersei', 'Jaime', 'Bran', 'Robb'], 'precond - array is initially sorted'); @@ -1195,7 +1197,7 @@ QUnit.test('changing item properties not specified via @each does not trigger a items = get(obj, 'items'); }); - cersei = items.objectAt(1); + cersei = objectAt(items, 1); deepEqual(sorted.mapBy('fname'), ['Cersei', 'Jaime', 'Bran', 'Robb'], 'precond - array is initially sorted'); @@ -1240,8 +1242,8 @@ QUnit.test('sorts correctly as only one property changes', function() { run(function() { sorted = obj.get('sortedItems'); }); - deepEqual(sorted.mapBy('name'), ['A', 'B', 'C', 'D'], 'initial'); - obj.get('items').objectAt(3).set('count', 2); + deepEqual(sorted.mapBy('name'), ['A', 'B', 'C', 'D'], "initial"); + objectAt(obj.get('items'), 3).set('count', 2); run(function() { sorted = obj.get('sortedItems'); }); @@ -1284,8 +1286,8 @@ QUnit.test('sorts correctly when there are concurrent changes', function() { }); deepEqual(sorted.mapBy('name'), ['A', 'B', 'C', 'D'], 'initial'); Ember.changeProperties(function() { - obj.get('items').objectAt(1).set('count', 5); - obj.get('items').objectAt(2).set('count', 6); + objectAt(obj.get('items'), 1).set('count', 5); + objectAt(obj.get('items'), 2).set('count', 6); }); run(function() { sorted = obj.get('sortedItems'); @@ -1302,8 +1304,8 @@ QUnit.test('sorts correctly with a user-provided comparator when there are concu run(function() { Ember.changeProperties(function() { - obj.get('items').objectAt(1).set('count', 5); - obj.get('items').objectAt(2).set('count', 6); + objectAt(obj.get('items'), 1).set('count', 5); + objectAt(obj.get('items'), 2).set('count', 6); }); sorted = obj.get('customSortedItems'); deepEqual(sorted.mapBy('name'), ['A', 'D', 'B', 'C'], 'final'); @@ -1541,7 +1543,7 @@ QUnit.test('it can filter and sort when both depend on the same item property', // 2. update filtered from item property change // // If 1.b happens before 2 it should invalidate 2 - todos.objectAt(1).set('priority', 6); + objectAt(todos, 1).set('priority', 6); endPropertyChanges(); }); diff --git a/packages/ember-runtime/tests/computed/reduce_computed_test.js b/packages/ember-runtime/tests/computed/reduce_computed_test.js index d7f62b55142..7ac32346d00 100644 --- a/packages/ember-runtime/tests/computed/reduce_computed_test.js +++ b/packages/ember-runtime/tests/computed/reduce_computed_test.js @@ -16,6 +16,7 @@ import { arrayComputed } from 'ember-runtime/computed/array_computed'; import { reduceComputed } from 'ember-runtime/computed/reduce_computed'; import ArrayProxy from 'ember-runtime/system/array_proxy'; import SubArray from 'ember-runtime/system/subarray'; +import { objectAt } from 'ember-runtime/mixins/array'; var obj, addCalls, removeCalls, callbackItems, shared; @@ -168,7 +169,7 @@ QUnit.test('after first retrieval, array computed properties can observe propert deepEqual(evenNestedNumbers, [2, 4, 6], 'precond -- starts off with correct values'); run(function() { - nestedNumbers.objectAt(0).set('v', 22); + objectAt(nestedNumbers, 0).set('v', 22); }); deepEqual(nestedNumbers.mapBy('v'), [22, 2, 3, 4, 5, 6], 'nested numbers is updated'); @@ -182,7 +183,7 @@ QUnit.test('changes to array computed properties happen synchronously', function deepEqual(evenNestedNumbers, [2, 4, 6], 'precond -- starts off with correct values'); run(function() { - nestedNumbers.objectAt(0).set('v', 22); + objectAt(nestedNumbers, 0).set('v', 22); deepEqual(nestedNumbers.mapBy('v'), [22, 2, 3, 4, 5, 6], 'nested numbers is updated'); deepEqual(evenNestedNumbers, [2, 4, 6, 22], 'adds new number'); }); @@ -638,7 +639,7 @@ QUnit.test('@this can be used to treat the object as the array itself', function deepEqual(names, ['a', 'b'], 'precond - names is initially correct'); run(function() { - obj.objectAt(1).set('name', 'c'); + objectAt(obj, 1).set('name', 'c'); }); deepEqual(names, ['a', 'c'], '@this can be used with item property observers'); @@ -714,7 +715,7 @@ QUnit.test('changeMeta includes item and index', function() { // remove0 add0 run(function() { - items.objectAt(0).set('n', 'zero\'\''); + objectAt(items, 0).set('n', "zero''"); }); expected = expected.concat(['add:2:five', 'add:3:six', 'remove:0:zero\'\'', 'add:0:zero\'\'']); @@ -723,7 +724,7 @@ QUnit.test('changeMeta includes item and index', function() { // [zero'', one, five, six] -> [zero'', five, six] // remove1 run(function() { - item = items.objectAt(1); + item = objectAt(items, 1); items.removeAt(1, 1); }); @@ -735,7 +736,7 @@ QUnit.test('changeMeta includes item and index', function() { // [zero'', five, six] -> [zero'', five, seven] // remove2 add2 run(function() { - items.objectAt(2).set('n', 'seven'); + objectAt(items, 2).set('n', "seven"); }); // observer should have been added to the new item @@ -744,7 +745,7 @@ QUnit.test('changeMeta includes item and index', function() { // reset (does not call remove) run(function() { - item = items.objectAt(1); + item = objectAt(items, 1); set(obj, 'items', Ember.A([])); }); diff --git a/packages/ember-runtime/tests/controllers/item_controller_class_test.js b/packages/ember-runtime/tests/controllers/item_controller_class_test.js index f12cee35b88..9e449430035 100644 --- a/packages/ember-runtime/tests/controllers/item_controller_class_test.js +++ b/packages/ember-runtime/tests/controllers/item_controller_class_test.js @@ -10,7 +10,8 @@ import Controller from 'ember-runtime/controllers/controller'; import {sort} from 'ember-runtime/computed/reduce_computed_macros'; import Registry from 'container/registry'; import { - addArrayObserver + addArrayObserver, + objectAt } from 'ember-runtime/mixins/array'; var lannisters, arrayController, controllerClass, otherControllerClass, registry, container, itemControllerCount, @@ -314,7 +315,7 @@ QUnit.test('array observers can invoke `objectAt` without overwriting existing i lannistersWillChange() { return this; }, lannistersDidChange(_, idx, removedAmt, addedAmt) { arrayObserverCalled = true; - equal(this.objectAt(idx).get('model.name'), 'Tyrion', 'Array observers get the right object via `objectAt`'); + equal(objectAt(this, idx).get('model.name'), "Tyrion", "Array observers get the right object via `objectAt`"); } }); diff --git a/packages/ember-runtime/tests/mixins/array_test.js b/packages/ember-runtime/tests/mixins/array_test.js index 777931b1bfe..25369437732 100644 --- a/packages/ember-runtime/tests/mixins/array_test.js +++ b/packages/ember-runtime/tests/mixins/array_test.js @@ -8,7 +8,8 @@ import { testBoth } from 'ember-metal/tests/props_helper'; import { ArrayTests } from 'ember-runtime/tests/suites/array'; import EmberObject from 'ember-runtime/system/object'; import EmberArray, { - addArrayObserver + addArrayObserver, + objectAt } from 'ember-runtime/mixins/array'; /* @@ -415,7 +416,7 @@ QUnit.test('modifying the array should also indicate the isDone prop itself has addObserver(each, 'isDone', function() { count++; }); count = 0; - var item = ary.objectAt(2); + var item = objectAt(ary, 2); set(item, 'isDone', !get(item, 'isDone')); equal(count, 1, '@each.isDone should have notified'); }); @@ -429,15 +430,15 @@ testBoth('should be clear caches for computed properties that have dependent key }, common: computed('resources.@each.common', function() { - return get(get(this, 'resources').objectAt(0), 'common'); + return get(objectAt(get(this, 'resources'), 0), 'common'); }) }).create(); get(obj, 'resources').pushObject(EmberObject.create({ common: 'HI!' })); equal('HI!', get(obj, 'common')); - set(get(obj, 'resources').objectAt(0), 'common', 'BYE!'); - equal('BYE!', get(obj, 'common')); + set(objectAt(get(obj, 'resources'), 0), 'common', "BYE!"); + equal("BYE!", get(obj, 'common')); }); testBoth('observers that contain @each in the path should fire only once the first time they are accessed', function(get, set) { @@ -458,7 +459,7 @@ testBoth('observers that contain @each in the path should fire only once the fir // Observer fires second time when new object is added get(obj, 'resources').pushObject(EmberObject.create({ common: 'HI!' })); // Observer fires third time when property on an object is changed - set(get(obj, 'resources').objectAt(0), 'common', 'BYE!'); + set(objectAt(get(obj, 'resources'), 0), 'common', "BYE!"); equal(count, 2, 'observers should only be called once'); }); diff --git a/packages/ember-runtime/tests/mixins/sortable_test.js b/packages/ember-runtime/tests/mixins/sortable_test.js index 62e1f69fde4..74cdbeaf536 100644 --- a/packages/ember-runtime/tests/mixins/sortable_test.js +++ b/packages/ember-runtime/tests/mixins/sortable_test.js @@ -7,6 +7,7 @@ import ArrayProxy from 'ember-runtime/system/array_proxy'; import SortableMixin from 'ember-runtime/mixins/sortable'; import EmberObject from 'ember-runtime/system/object'; import ArrayController, { arrayControllerDeprecation } from 'ember-runtime/controllers/array_controller'; +import { objectAt } from 'ember-runtime/mixins/array'; var unsortedArray, sortedArrayController; @@ -272,7 +273,7 @@ QUnit.test('don\'t remove and insert if position didn\'t change', function() { }); QUnit.test('sortProperties observers removed on content removal', function() { - var removedObject = unsortedArray.objectAt(2); + var removedObject = objectAt(unsortedArray, 2); equal(listenersFor(removedObject, 'name:change').length, 1, 'Before removal, there should be one listener for sortProperty change.'); unsortedArray.replace(2, 1, []); diff --git a/packages/ember-runtime/tests/suites/array/objectAt.js b/packages/ember-runtime/tests/suites/array/objectAt.js index 6a5d6a16225..af544e07314 100644 --- a/packages/ember-runtime/tests/suites/array/objectAt.js +++ b/packages/ember-runtime/tests/suites/array/objectAt.js @@ -1,5 +1,5 @@ -import {SuiteModuleBuilder} from 'ember-runtime/tests/suites/suite'; -import {fmt} from 'ember-runtime/system/string'; +import { SuiteModuleBuilder } from 'ember-runtime/tests/suites/suite'; +import { objectAt } from 'ember-runtime/mixins/array'; var suite = SuiteModuleBuilder.create(); @@ -12,7 +12,7 @@ suite.test('should return object at specified index', function() { var idx; for (idx=0;idx