From cd0d1868fe33cceeed31765888055709b600b352 Mon Sep 17 00:00:00 2001 From: Bj Date: Tue, 9 Feb 2016 21:45:55 -0500 Subject: [PATCH 1/2] [BUGFIX beta] Do not rely prototype extensions (objectAt) Do not use prototype extension for `objectAt`. Related to #9269 and based on the work of @stefanpenner in #10899. If this is acceptable, will continue addressing one extension at a time for quicker merging. --- .../lib/data_adapter.js | 3 +- .../tests/helpers/collection_test.js | 6 ++-- .../ember-htmlbars/tests/helpers/view_test.js | 6 ++-- packages/ember-runtime/lib/mixins/array.js | 34 +++++++++++-------- .../ember-runtime/lib/mixins/mutable_array.js | 8 ++--- .../ember-runtime/lib/system/array_proxy.js | 5 +-- .../ember-runtime/lib/system/each_proxy.js | 5 +-- .../ember-runtime/tests/mixins/array_test.js | 10 +++--- .../tests/suites/array/objectAt.js | 7 ++-- .../array_proxy/arranged_content_test.js | 7 ++-- .../ember-views/lib/views/collection_view.js | 4 +-- packages/ember-views/lib/views/select.js | 4 ++- .../tests/views/container_view_test.js | 18 +++++----- .../tests/views/view/destroy_element_test.js | 4 ++- .../tests/views/view/element_test.js | 4 ++- .../tests/views/view/is_visible_test.js | 8 +++-- .../tests/views/view/remove_test.js | 8 +++-- 17 files changed, 83 insertions(+), 58 deletions(-) diff --git a/packages/ember-extension-support/lib/data_adapter.js b/packages/ember-extension-support/lib/data_adapter.js index 855ddaaff50..2acb8a4f530 100644 --- a/packages/ember-extension-support/lib/data_adapter.js +++ b/packages/ember-extension-support/lib/data_adapter.js @@ -6,6 +6,7 @@ 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 { getOwner } from 'container/owner'; +import { objectAt } from 'ember-runtime/mixins/array'; /** @module ember @@ -206,7 +207,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 8c02552c79c..be28d3c5b80 100644 --- a/packages/ember-htmlbars/tests/helpers/collection_test.js +++ b/packages/ember-htmlbars/tests/helpers/collection_test.js @@ -19,6 +19,8 @@ import { OWNER } from 'container/owner'; import { registerKeyword, resetKeyword } from 'ember-htmlbars/tests/utils'; import viewKeyword from 'ember-htmlbars/keywords/view'; +import { objectAt } from 'ember-runtime/mixins/array'; + var trim = jQuery.trim; var view; @@ -28,13 +30,13 @@ var TemplateTests, owner, lookup, originalViewKeyword; 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 [LEGACY]', { diff --git a/packages/ember-htmlbars/tests/helpers/view_test.js b/packages/ember-htmlbars/tests/helpers/view_test.js index 88d54cf8818..5d7c277af8f 100644 --- a/packages/ember-htmlbars/tests/helpers/view_test.js +++ b/packages/ember-htmlbars/tests/helpers/view_test.js @@ -28,16 +28,18 @@ import viewKeyword from 'ember-htmlbars/keywords/view'; import { OWNER } from 'container/owner'; import buildOwner from 'container/tests/test-helpers/build-owner'; +import { objectAt } from 'ember-runtime/mixins/array'; + var view, originalLookup, owner, lookup, originalViewKeyword; 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/mixins/array.js b/packages/ember-runtime/lib/mixins/array.js index 793a2081d5e..8fa4205e09f 100644 --- a/packages/ember-runtime/lib/mixins/array.js +++ b/packages/ember-runtime/lib/mixins/array.js @@ -47,6 +47,14 @@ function arrayObserversHelper(obj, target, opts, operation, notify) { return obj; } +export function objectAt(content, idx) { + if (content.objectAt) { + return content.objectAt(idx); + } + + return content[idx]; +} + // .......................................................... // ARRAY // @@ -148,16 +156,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); }, /** @@ -182,11 +186,11 @@ export default Mixin.create(Enumerable, { }), firstObject: computed(function() { - return this.objectAt(0); + return objectAt(this, 0); }), lastObject: computed(function() { - return this.objectAt(get(this, 'length') - 1); + return objectAt(this, get(this, 'length') - 1); }), // optimized version from Enumerable @@ -235,7 +239,7 @@ export default Mixin.create(Enumerable, { } while (beginIndex < endIndex) { - ret[ret.length] = this.objectAt(beginIndex++); + ret[ret.length] = objectAt(this, beginIndex++); } return ret; @@ -277,7 +281,7 @@ export default Mixin.create(Enumerable, { } for (idx = startAt; idx < len; idx++) { - if (this.objectAt(idx) === object) { + if (objectAt(this, idx) === object) { return idx; } } @@ -321,7 +325,7 @@ export default Mixin.create(Enumerable, { } for (idx = startAt; idx >= 0; idx--) { - if (this.objectAt(idx) === object) { + if (objectAt(this, idx) === object) { return idx; } } @@ -434,7 +438,7 @@ export default Mixin.create(Enumerable, { lim = startIdx + removeAmt; for (var idx = startIdx; idx < lim; idx++) { - removing.push(this.objectAt(idx)); + removing.push(objectAt(this, idx)); } } else { removing = removeAmt; @@ -482,7 +486,7 @@ export default Mixin.create(Enumerable, { lim = startIdx + addAmt; for (var idx = startIdx; idx < lim; idx++) { - adding.push(this.objectAt(idx)); + adding.push(objectAt(this, idx)); } } else { adding = addAmt; @@ -500,12 +504,12 @@ export default Mixin.create(Enumerable, { var cachedFirst = cacheFor(this, 'firstObject'); var cachedLast = cacheFor(this, 'lastObject'); - if (this.objectAt(0) !== cachedFirst) { + if (objectAt(this, 0) !== cachedFirst) { propertyWillChange(this, 'firstObject'); propertyDidChange(this, 'firstObject'); } - if (this.objectAt(length - 1) !== cachedLast) { + if (objectAt(this, length - 1) !== cachedLast) { propertyWillChange(this, 'lastObject'); propertyDidChange(this, 'lastObject'); } diff --git a/packages/ember-runtime/lib/mixins/mutable_array.js b/packages/ember-runtime/lib/mixins/mutable_array.js index 6c5c53c243c..d6deb9c3a60 100644 --- a/packages/ember-runtime/lib/mixins/mutable_array.js +++ b/packages/ember-runtime/lib/mixins/mutable_array.js @@ -21,7 +21,7 @@ var EMPTY = []; import { get } from 'ember-metal/property_get'; import EmberError from 'ember-metal/error'; import { Mixin } from 'ember-metal/mixin'; -import EmberArray from 'ember-runtime/mixins/array'; +import EmberArray, { objectAt } from 'ember-runtime/mixins/array'; import MutableEnumerable from 'ember-runtime/mixins/mutable_enumerable'; import Enumerable from 'ember-runtime/mixins/enumerable'; @@ -221,7 +221,7 @@ export default Mixin.create(EmberArray, MutableEnumerable, { return null; } - var ret = this.objectAt(len - 1); + var ret = objectAt(this, len - 1); this.removeAt(len - 1, 1); return ret; }, @@ -246,7 +246,7 @@ export default Mixin.create(EmberArray, MutableEnumerable, { return null; } - var ret = this.objectAt(0); + var ret = objectAt(this, 0); this.removeAt(0); return ret; }, @@ -362,7 +362,7 @@ export default Mixin.create(EmberArray, MutableEnumerable, { removeObject(obj) { var loc = get(this, 'length') || 0; while (--loc >= 0) { - var curObject = this.objectAt(loc); + var curObject = objectAt(this, loc); if (curObject === obj) { this.removeAt(loc); diff --git a/packages/ember-runtime/lib/system/array_proxy.js b/packages/ember-runtime/lib/system/array_proxy.js index 498bdeb9be5..b7acb3834fa 100644 --- a/packages/ember-runtime/lib/system/array_proxy.js +++ b/packages/ember-runtime/lib/system/array_proxy.js @@ -17,6 +17,7 @@ import EmberObject from 'ember-runtime/system/object'; import MutableArray from 'ember-runtime/mixins/mutable_array'; import Enumerable from 'ember-runtime/mixins/enumerable'; import alias from 'ember-metal/alias'; +import { objectAt } from 'ember-runtime/mixins/array'; /** @module ember @@ -102,7 +103,7 @@ var ArrayProxy = EmberObject.extend(MutableArray, { @private */ objectAtContent(idx) { - return get(this, 'arrangedContent').objectAt(idx); + return objectAt(get(this, 'arrangedContent'), idx); }, /** @@ -312,7 +313,7 @@ var ArrayProxy = EmberObject.extend(MutableArray, { // Get a list of indices in original content to remove for (i = start; i < start + len; i++) { // Use arrangedContent here so we avoid confusion with objects transformed by objectAtContent - indices.push(content.indexOf(arrangedContent.objectAt(i))); + indices.push(content.indexOf(objectAt(arrangedContent, i))); } // Replace in reverse order since indices will change diff --git a/packages/ember-runtime/lib/system/each_proxy.js b/packages/ember-runtime/lib/system/each_proxy.js index b049d9b1eb6..d95c0324818 100644 --- a/packages/ember-runtime/lib/system/each_proxy.js +++ b/packages/ember-runtime/lib/system/each_proxy.js @@ -11,6 +11,7 @@ import { propertyWillChange } from 'ember-metal/property_events'; import EmptyObject from 'ember-metal/empty_object'; +import { objectAt } from 'ember-runtime/mixins/array'; /** This is the object instance returned when you get the `@each` property on an @@ -110,7 +111,7 @@ EachProxy.prototype = { function addObserverForContentKey(content, keyName, proxy, idx, loc) { while (--loc >= idx) { - let item = content.objectAt(loc); + let item = objectAt(content, loc); if (item) { assert('When using @each to observe the array ' + content + ', the array must return an object', typeof item === 'object'); _addBeforeObserver(item, keyName, proxy, 'contentKeyWillChange'); @@ -121,7 +122,7 @@ function addObserverForContentKey(content, keyName, proxy, idx, loc) { function removeObserverForContentKey(content, keyName, proxy, idx, loc) { while (--loc >= idx) { - let item = content.objectAt(loc); + let item = objectAt(content, loc); if (item) { _removeBeforeObserver(item, keyName, proxy, 'contentKeyWillChange'); removeObserver(item, keyName, proxy, 'contentKeyDidChange'); diff --git a/packages/ember-runtime/tests/mixins/array_test.js b/packages/ember-runtime/tests/mixins/array_test.js index 38c60e7a45b..fbe92cfad93 100644 --- a/packages/ember-runtime/tests/mixins/array_test.js +++ b/packages/ember-runtime/tests/mixins/array_test.js @@ -6,7 +6,7 @@ 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, { objectAt } from 'ember-runtime/mixins/array'; import { A as emberA } from 'ember-runtime/system/native_array'; /* @@ -385,7 +385,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'); }); @@ -399,14 +399,14 @@ 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!'); + set(objectAt(get(obj, 'resources'), 0), 'common', 'BYE!'); equal('BYE!', get(obj, 'common')); }); @@ -428,7 +428,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/suites/array/objectAt.js b/packages/ember-runtime/tests/suites/array/objectAt.js index 023bcab643c..e9cea5bcbae 100644 --- a/packages/ember-runtime/tests/suites/array/objectAt.js +++ b/packages/ember-runtime/tests/suites/array/objectAt.js @@ -1,4 +1,5 @@ import {SuiteModuleBuilder} from 'ember-runtime/tests/suites/suite'; +import { objectAt } from 'ember-runtime/mixins/array'; var suite = SuiteModuleBuilder.create(); @@ -11,7 +12,7 @@ suite.test('should return object at specified index', function() { var idx; for (idx = 0;idx < len;idx++) { - equal(obj.objectAt(idx), expected[idx], `obj.objectAt(${idx}) should match`); + equal(objectAt(obj, idx), expected[idx], `obj.objectAt(${idx}) should match`); } }); @@ -19,10 +20,10 @@ suite.test('should return undefined when requesting objects beyond index', funct var obj; obj = this.newObject(this.newFixture(3)); - equal(obj.objectAt(5), undefined, 'should return undefined for obj.objectAt(5) when len = 3'); + equal(objectAt(obj, 5), undefined, 'should return undefined for obj.objectAt(5) when len = 3'); obj = this.newObject([]); - equal(obj.objectAt(0), undefined, 'should return undefined for obj.objectAt(0) when len = 0'); + equal(objectAt(obj, 0), undefined, 'should return undefined for obj.objectAt(0) when len = 0'); }); export default suite; diff --git a/packages/ember-runtime/tests/system/array_proxy/arranged_content_test.js b/packages/ember-runtime/tests/system/array_proxy/arranged_content_test.js index f37ea684307..9971270d06c 100644 --- a/packages/ember-runtime/tests/system/array_proxy/arranged_content_test.js +++ b/packages/ember-runtime/tests/system/array_proxy/arranged_content_test.js @@ -2,6 +2,7 @@ import run from 'ember-metal/run_loop'; import { computed } from 'ember-metal/computed'; import ArrayProxy from 'ember-runtime/system/array_proxy'; import { A as emberA } from 'ember-runtime/system/native_array'; +import { objectAt } from 'ember-runtime/mixins/array'; var array; @@ -69,7 +70,7 @@ QUnit.test('nextObject - returns object at index in arrangedContent', function() }); QUnit.test('objectAt - returns object at index in arrangedContent', function() { - equal(array.objectAt(1), 4, 'returns object at index'); + equal(objectAt(array, 1), 4, 'returns object at index'); }); // Not sure if we need a specific test for it, since it's internal @@ -217,7 +218,7 @@ QUnit.module('ArrayProxy - arrangedContent with transforms', { }).property('content.[]'), objectAtContent(idx) { - var obj = this.get('arrangedContent').objectAt(idx); + var obj = objectAt(this.get('arrangedContent'), idx); return obj && obj.toString(); } }).create({ @@ -246,7 +247,7 @@ QUnit.test('nextObject - returns object at index in arrangedContent', function() }); QUnit.test('objectAt - returns object at index in arrangedContent', function() { - equal(array.objectAt(1), '4', 'returns object at index'); + equal(objectAt(array, 1), '4', 'returns object at index'); }); // Not sure if we need a specific test for it, since it's internal diff --git a/packages/ember-views/lib/views/collection_view.js b/packages/ember-views/lib/views/collection_view.js index 25a9ed15298..7308ea7b6ea 100644 --- a/packages/ember-views/lib/views/collection_view.js +++ b/packages/ember-views/lib/views/collection_view.js @@ -7,7 +7,7 @@ import Ember from 'ember-metal/core'; import { assert, deprecate } from 'ember-metal/debug'; import ContainerView from 'ember-views/views/container_view'; import View from 'ember-views/views/view'; -import EmberArray from 'ember-runtime/mixins/array'; +import EmberArray, { objectAt } from 'ember-runtime/mixins/array'; import { get } from 'ember-metal/property_get'; import { set } from 'ember-metal/property_set'; import { computed } from 'ember-metal/computed'; @@ -315,7 +315,7 @@ var CollectionView = ContainerView.extend(EmptyViewSupport, { itemViewClass = readViewFactory(itemViewClass, getOwner(this)); for (idx = start; idx < start + added; idx++) { - item = content.objectAt(idx); + item = objectAt(content, idx); itemViewProps._context = this.keyword ? this.get('context') : item; itemViewProps.content = item; itemViewProps.contentIndex = idx; diff --git a/packages/ember-views/lib/views/select.js b/packages/ember-views/lib/views/select.js index fae8e523176..a3a63a4f294 100644 --- a/packages/ember-views/lib/views/select.js +++ b/packages/ember-views/lib/views/select.js @@ -18,6 +18,8 @@ import htmlbarsTemplate from 'ember-htmlbars/templates/select'; import selectOptionDefaultTemplate from 'ember-htmlbars/templates/select-option'; import selectOptgroupDefaultTemplate from 'ember-htmlbars/templates/select-optgroup'; +import { objectAt } from 'ember-runtime/mixins/array'; + var defaultTemplate = htmlbarsTemplate; var SelectOption = View.extend({ @@ -565,7 +567,7 @@ var Select = View.extend({ } if (prompt) { selectedIndex -= 1; } - set(this, 'selection', content.objectAt(selectedIndex)); + set(this, 'selection', objectAt(content, selectedIndex)); }, _selectedIndex(value, defaultIndex = 0) { diff --git a/packages/ember-views/tests/views/container_view_test.js b/packages/ember-views/tests/views/container_view_test.js index 27720b249d6..c10e8c2d490 100644 --- a/packages/ember-views/tests/views/container_view_test.js +++ b/packages/ember-views/tests/views/container_view_test.js @@ -14,6 +14,8 @@ import { getOwner, OWNER } from 'container/owner'; import { registerKeyword, resetKeyword } from 'ember-htmlbars/tests/utils'; import viewKeyword from 'ember-htmlbars/keywords/view'; +import { objectAt } from 'ember-runtime/mixins/array'; + var trim = jQuery.trim; var container, view, otherContainer, originalViewKeyword; @@ -295,7 +297,7 @@ QUnit.test('if a ContainerView starts with a currentView, it is rendered as a ch equal(trim(container.$().text()), 'This is the main view.', 'should render its child'); equal(get(container, 'length'), 1, 'should have one child view'); - equal(container.objectAt(0), mainView, 'should have the currentView as the only child view'); + equal(objectAt(container, 0), mainView, 'should have the currentView as the only child view'); equal(mainView.get('parentView'), container, 'parentView is setup'); }); @@ -317,7 +319,7 @@ QUnit.test('if a ContainerView is created with a currentView, it is rendered as equal(container.$().text(), 'This is the main view.', 'should render its child'); equal(get(container, 'length'), 1, 'should have one child view'); - equal(container.objectAt(0), mainView, 'should have the currentView as the only child view'); + equal(objectAt(container, 0), mainView, 'should have the currentView as the only child view'); equal(mainView.get('parentView'), container, 'parentView is setup'); }); @@ -347,7 +349,7 @@ QUnit.test('if a ContainerView starts with no currentView and then one is set, t equal(container.$().text(), 'This is the main view.', 'should render its child'); equal(get(container, 'length'), 1, 'should have one child view'); - equal(container.objectAt(0), mainView, 'should have the currentView as the only child view'); + equal(objectAt(container, 0), mainView, 'should have the currentView as the only child view'); equal(mainView.get('parentView'), container, 'parentView is setup'); }); @@ -370,7 +372,7 @@ QUnit.test('if a ContainerView starts with a currentView and then is set to null equal(container.$().text(), 'This is the main view.', 'should render its child'); equal(get(container, 'length'), 1, 'should have one child view'); - equal(container.objectAt(0), mainView, 'should have the currentView as the only child view'); + equal(objectAt(container, 0), mainView, 'should have the currentView as the only child view'); equal(mainView.get('parentView'), container, 'parentView is setup'); run(function() { @@ -400,7 +402,7 @@ QUnit.test('if a ContainerView starts with a currentView and then is set to null equal(container.$().text(), 'This is the main view.', 'should render its child'); equal(get(container, 'length'), 1, 'should have one child view'); - equal(container.objectAt(0), mainView, 'should have the currentView as the only child view'); + equal(objectAt(container, 0), mainView, 'should have the currentView as the only child view'); equal(mainView.get('parentView'), container, 'parentView is setup'); run(function() { @@ -435,14 +437,14 @@ QUnit.test('if a ContainerView starts with a currentView and then a different cu equal(container.$().text(), 'This is the main view.', 'should render its child'); equal(get(container, 'length'), 1, 'should have one child view'); - equal(container.objectAt(0), mainView, 'should have the currentView as the only child view'); + equal(objectAt(container, 0), mainView, 'should have the currentView as the only child view'); run(function() { set(container, 'currentView', secondaryView); }); equal(get(container, 'length'), 1, 'should have one child view'); - equal(container.objectAt(0), secondaryView, 'should have the currentView as the only child view'); + equal(objectAt(container, 0), secondaryView, 'should have the currentView as the only child view'); equal(mainView.isDestroyed, true, 'should destroy the previous currentView: mainView.'); equal(trim(container.$().text()), 'This is the secondary view.', 'should render its child'); @@ -452,7 +454,7 @@ QUnit.test('if a ContainerView starts with a currentView and then a different cu }); equal(get(container, 'length'), 1, 'should have one child view'); - equal(container.objectAt(0), tertiaryView, 'should have the currentView as the only child view'); + equal(objectAt(container, 0), tertiaryView, 'should have the currentView as the only child view'); equal(secondaryView.isDestroyed, true, 'should destroy the previous currentView: secondaryView.'); equal(trim(container.$().text()), 'This is the tertiary view.', 'should render its child'); diff --git a/packages/ember-views/tests/views/view/destroy_element_test.js b/packages/ember-views/tests/views/view/destroy_element_test.js index ff600403f65..cb7d1bcfcc6 100644 --- a/packages/ember-views/tests/views/view/destroy_element_test.js +++ b/packages/ember-views/tests/views/view/destroy_element_test.js @@ -6,6 +6,8 @@ import ContainerView from 'ember-views/views/container_view'; import { registerKeyword, resetKeyword } from 'ember-htmlbars/tests/utils'; import viewKeyword from 'ember-htmlbars/keywords/view'; +import { objectAt } from 'ember-runtime/mixins/array'; + var originalViewKeyword; var view; @@ -65,7 +67,7 @@ QUnit.test('if it has a element, calls willDestroyElement on receiver and child equal(parentCount, 1, 'invoked destroy element on the parent'); equal(childCount, 1, 'invoked destroy element on the child'); ok(!get(view, 'element'), 'view no longer has element'); - ok(!get(get(view, 'childViews').objectAt(0), 'element'), 'child no longer has an element'); + ok(!get(objectAt(get(view, 'childViews'), 0), 'element'), 'child no longer has an element'); }); QUnit.test('returns receiver', function() { diff --git a/packages/ember-views/tests/views/view/element_test.js b/packages/ember-views/tests/views/view/element_test.js index 239d61315ef..7b62f270226 100644 --- a/packages/ember-views/tests/views/view/element_test.js +++ b/packages/ember-views/tests/views/view/element_test.js @@ -7,6 +7,8 @@ import run from 'ember-metal/run_loop'; import EmberView from 'ember-views/views/view'; import ContainerView from 'ember-views/views/container_view'; +import { objectAt } from 'ember-runtime/mixins/array'; + var parentView, view; QUnit.module('Ember.View#element', { @@ -30,7 +32,7 @@ QUnit.test('returns null if the view has no element and parent view has no eleme parentView = ContainerView.create({ childViews: [EmberView.extend()] }); - view = get(parentView, 'childViews').objectAt(0); + view = objectAt(get(parentView, 'childViews'), 0); equal(get(view, 'parentView'), parentView, 'precond - has parent view'); equal(get(parentView, 'element'), null, 'parentView has no element'); diff --git a/packages/ember-views/tests/views/view/is_visible_test.js b/packages/ember-views/tests/views/view/is_visible_test.js index 4e05811d7d2..c9b5e2ca89c 100644 --- a/packages/ember-views/tests/views/view/is_visible_test.js +++ b/packages/ember-views/tests/views/view/is_visible_test.js @@ -9,6 +9,8 @@ import ContainerView from 'ember-views/views/container_view'; import { registerKeyword, resetKeyword } from 'ember-htmlbars/tests/utils'; import viewKeyword from 'ember-htmlbars/keywords/view'; +import { objectAt } from 'ember-runtime/mixins/array'; + var View, view, parentBecameVisible, childBecameVisible, grandchildBecameVisible; var parentBecameHidden, childBecameHidden, grandchildBecameHidden; var warnings, originalWarn; @@ -210,7 +212,7 @@ QUnit.test('view should be notified after isVisible is set to false and the elem QUnit.test('view should be notified after isVisible is set to false and the element has been hidden', function() { view = View.create({ isVisible: true }); - //var childView = view.get('childViews').objectAt(0); + //var childView = objectAt(view.get('childViews'), 0); run(function() { view.append(); @@ -247,7 +249,7 @@ QUnit.test('view should be notified after isVisible is set to true and the eleme QUnit.test('if a view descends from a hidden view, making isVisible true should not trigger becameVisible', function() { view = View.create({ isVisible: true }); - var childView = view.get('childViews').objectAt(0); + var childView = objectAt(view.get('childViews'), 0); run(function() { view.append(); @@ -276,7 +278,7 @@ QUnit.test('if a view descends from a hidden view, making isVisible true should QUnit.test('if a child view becomes visible while its parent is hidden, if its parent later becomes visible, it receives a becameVisible callback', function() { view = View.create({ isVisible: false }); - var childView = view.get('childViews').objectAt(0); + var childView = objectAt(view.get('childViews'), 0); run(function() { view.append(); diff --git a/packages/ember-views/tests/views/view/remove_test.js b/packages/ember-views/tests/views/view/remove_test.js index 28e3f109325..947330ec7a6 100644 --- a/packages/ember-views/tests/views/view/remove_test.js +++ b/packages/ember-views/tests/views/view/remove_test.js @@ -7,6 +7,8 @@ import ContainerView from 'ember-views/views/container_view'; import { registerKeyword, resetKeyword } from 'ember-htmlbars/tests/utils'; import viewKeyword from 'ember-htmlbars/keywords/view'; +import { objectAt } from 'ember-runtime/mixins/array'; + // ....................................................... // removeChild() @@ -20,7 +22,7 @@ QUnit.module('View#removeChild', { expectDeprecation('Setting `childViews` on a Container is deprecated.'); parentView = ContainerView.create({ childViews: [View] }); - child = get(parentView, 'childViews').objectAt(0); + child = objectAt(get(parentView, 'childViews'), 0); }, teardown() { run(function() { @@ -102,7 +104,7 @@ QUnit.test('removes view from parent view', function() { expectDeprecation('Setting `childViews` on a Container is deprecated.'); parentView = ContainerView.create({ childViews: [View] }); - child = get(parentView, 'childViews').objectAt(0); + child = objectAt(get(parentView, 'childViews'), 0); ok(get(child, 'parentView'), 'precond - has parentView'); run(function() { @@ -124,7 +126,7 @@ QUnit.test('returns receiver', function() { expectDeprecation('Setting `childViews` on a Container is deprecated.'); parentView = ContainerView.create({ childViews: [View] }); - child = get(parentView, 'childViews').objectAt(0); + child = objectAt(get(parentView, 'childViews'), 0); var removed = run(function() { return child.removeFromParent(); }); From f5377739b4d59fc3b522756ca73f37e6c1e6c004 Mon Sep 17 00:00:00 2001 From: Bj Date: Tue, 9 Feb 2016 22:50:38 -0500 Subject: [PATCH 2/2] Add unit test for `objectAt` --- packages/ember-runtime/tests/mixins/array_test.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/ember-runtime/tests/mixins/array_test.js b/packages/ember-runtime/tests/mixins/array_test.js index fbe92cfad93..93d98bf26eb 100644 --- a/packages/ember-runtime/tests/mixins/array_test.js +++ b/packages/ember-runtime/tests/mixins/array_test.js @@ -390,6 +390,11 @@ QUnit.test('modifying the array should also indicate the isDone prop itself has equal(count, 1, '@each.isDone should have notified'); }); +QUnit.test('`objectAt` returns correct object', function() { + let arr = ['first', 'second', 'third', 'fourth']; + equal(objectAt(arr, 2), 'third'); + equal(objectAt(arr, 4), undefined); +}); testBoth('should be clear caches for computed properties that have dependent keys on arrays that are changed after object initialization', function(get, set) { var obj = EmberObject.extend({