Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUGFIX beta] Do not rely prototype extensions (objectAt) #12942

Merged
merged 2 commits into from
Feb 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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