Skip to content

Commit

Permalink
Merge pull request #12942 from btecu/objectAt
Browse files Browse the repository at this point in the history
[BUGFIX beta] Do not rely prototype extensions (objectAt)
  • Loading branch information
stefanpenner committed Feb 10, 2016
2 parents c81bca9 + f537773 commit 58f5a9a
Show file tree
Hide file tree
Showing 17 changed files with 88 additions and 58 deletions.
3 changes: 2 additions & 1 deletion packages/ember-extension-support/lib/data_adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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]);
Expand Down
6 changes: 4 additions & 2 deletions packages/ember-htmlbars/tests/helpers/collection_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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]', {
Expand Down
6 changes: 4 additions & 2 deletions packages/ember-htmlbars/tests/helpers/view_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
34 changes: 19 additions & 15 deletions packages/ember-runtime/lib/mixins/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
//
Expand Down Expand Up @@ -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);
},

/**
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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');
}
Expand Down
8 changes: 4 additions & 4 deletions packages/ember-runtime/lib/mixins/mutable_array.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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;
},
Expand All @@ -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;
},
Expand Down Expand Up @@ -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);
Expand Down
5 changes: 3 additions & 2 deletions packages/ember-runtime/lib/system/array_proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -102,7 +103,7 @@ var ArrayProxy = EmberObject.extend(MutableArray, {
@private
*/
objectAtContent(idx) {
return get(this, 'arrangedContent').objectAt(idx);
return objectAt(get(this, 'arrangedContent'), idx);
},

/**
Expand Down Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions packages/ember-runtime/lib/system/each_proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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');
Expand All @@ -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');
Expand Down
15 changes: 10 additions & 5 deletions packages/ember-runtime/tests/mixins/array_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

/*
Expand Down Expand Up @@ -385,11 +385,16 @@ 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');
});

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({
Expand All @@ -399,14 +404,14 @@ testBoth('should be clear caches for computed properties that have dependent key
},

common: computed('[email protected]', 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'));
});

Expand All @@ -428,7 +433,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');
});
7 changes: 4 additions & 3 deletions packages/ember-runtime/tests/suites/array/objectAt.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {SuiteModuleBuilder} from 'ember-runtime/tests/suites/suite';
import { objectAt } from 'ember-runtime/mixins/array';

var suite = SuiteModuleBuilder.create();

Expand All @@ -11,18 +12,18 @@ 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`);
}
});

suite.test('should return undefined when requesting objects beyond index', function() {
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;
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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({
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions packages/ember-views/lib/views/collection_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
Expand Down
Loading

0 comments on commit 58f5a9a

Please sign in to comment.