Skip to content

Commit 58f5a9a

Browse files
committed
Merge pull request #12942 from btecu/objectAt
[BUGFIX beta] Do not rely prototype extensions (objectAt)
2 parents c81bca9 + f537773 commit 58f5a9a

File tree

17 files changed

+88
-58
lines changed

17 files changed

+88
-58
lines changed

packages/ember-extension-support/lib/data_adapter.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import EmberObject from 'ember-runtime/system/object';
66
import { A as emberA } from 'ember-runtime/system/native_array';
77
import Application from 'ember-application/system/application';
88
import { getOwner } from 'container/owner';
9+
import { objectAt } from 'ember-runtime/mixins/array';
910

1011
/**
1112
@module ember
@@ -206,7 +207,7 @@ export default EmberObject.extend({
206207

207208
var contentDidChange = (array, idx, removedCount, addedCount) => {
208209
for (var i = idx; i < idx + addedCount; i++) {
209-
var record = array.objectAt(i);
210+
var record = objectAt(array, i);
210211
var wrapped = this.wrapRecord(record);
211212
releaseMethods.push(this.observeRecord(record, recordUpdated));
212213
recordsAdded([wrapped]);

packages/ember-htmlbars/tests/helpers/collection_test.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import { OWNER } from 'container/owner';
1919
import { registerKeyword, resetKeyword } from 'ember-htmlbars/tests/utils';
2020
import viewKeyword from 'ember-htmlbars/keywords/view';
2121

22+
import { objectAt } from 'ember-runtime/mixins/array';
23+
2224
var trim = jQuery.trim;
2325

2426
var view;
@@ -28,13 +30,13 @@ var TemplateTests, owner, lookup, originalViewKeyword;
2830

2931

3032
function nthChild(view, nth) {
31-
return get(view, 'childViews').objectAt(nth || 0);
33+
return objectAt(get(view, 'childViews'), nth || 0);
3234
}
3335

3436
var firstChild = nthChild;
3537

3638
function firstGrandchild(view) {
37-
return get(get(view, 'childViews').objectAt(0), 'childViews').objectAt(0);
39+
return objectAt(get(objectAt(get(view, 'childViews'), 0), 'childViews'), 0);
3840
}
3941

4042
QUnit.module('collection helper [LEGACY]', {

packages/ember-htmlbars/tests/helpers/view_test.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,18 @@ import viewKeyword from 'ember-htmlbars/keywords/view';
2828
import { OWNER } from 'container/owner';
2929
import buildOwner from 'container/tests/test-helpers/build-owner';
3030

31+
import { objectAt } from 'ember-runtime/mixins/array';
32+
3133
var view, originalLookup, owner, lookup, originalViewKeyword;
3234

3335
var trim = jQuery.trim;
3436

3537
function firstGrandchild(view) {
36-
return get(get(view, 'childViews').objectAt(0), 'childViews').objectAt(0);
38+
return objectAt(get(objectAt(get(view, 'childViews'), 0), 'childViews'), 0);
3739
}
3840

3941
function nthChild(view, nth) {
40-
return get(view, 'childViews').objectAt(nth || 0);
42+
return objectAt(get(view, 'childViews'), nth || 0);
4143
}
4244

4345
function viewClass(options) {

packages/ember-runtime/lib/mixins/array.js

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ function arrayObserversHelper(obj, target, opts, operation, notify) {
4747
return obj;
4848
}
4949

50+
export function objectAt(content, idx) {
51+
if (content.objectAt) {
52+
return content.objectAt(idx);
53+
}
54+
55+
return content[idx];
56+
}
57+
5058
// ..........................................................
5159
// ARRAY
5260
//
@@ -148,16 +156,12 @@ export default Mixin.create(Enumerable, {
148156
@public
149157
*/
150158
objectsAt(indexes) {
151-
var self = this;
152-
153-
return indexes.map(function(idx) {
154-
return self.objectAt(idx);
155-
});
159+
return indexes.map(idx => objectAt(this, idx));
156160
},
157161

158162
// overrides Ember.Enumerable version
159163
nextObject(idx) {
160-
return this.objectAt(idx);
164+
return objectAt(this, idx);
161165
},
162166

163167
/**
@@ -182,11 +186,11 @@ export default Mixin.create(Enumerable, {
182186
}),
183187

184188
firstObject: computed(function() {
185-
return this.objectAt(0);
189+
return objectAt(this, 0);
186190
}),
187191

188192
lastObject: computed(function() {
189-
return this.objectAt(get(this, 'length') - 1);
193+
return objectAt(this, get(this, 'length') - 1);
190194
}),
191195

192196
// optimized version from Enumerable
@@ -235,7 +239,7 @@ export default Mixin.create(Enumerable, {
235239
}
236240

237241
while (beginIndex < endIndex) {
238-
ret[ret.length] = this.objectAt(beginIndex++);
242+
ret[ret.length] = objectAt(this, beginIndex++);
239243
}
240244

241245
return ret;
@@ -277,7 +281,7 @@ export default Mixin.create(Enumerable, {
277281
}
278282

279283
for (idx = startAt; idx < len; idx++) {
280-
if (this.objectAt(idx) === object) {
284+
if (objectAt(this, idx) === object) {
281285
return idx;
282286
}
283287
}
@@ -321,7 +325,7 @@ export default Mixin.create(Enumerable, {
321325
}
322326

323327
for (idx = startAt; idx >= 0; idx--) {
324-
if (this.objectAt(idx) === object) {
328+
if (objectAt(this, idx) === object) {
325329
return idx;
326330
}
327331
}
@@ -434,7 +438,7 @@ export default Mixin.create(Enumerable, {
434438
lim = startIdx + removeAmt;
435439

436440
for (var idx = startIdx; idx < lim; idx++) {
437-
removing.push(this.objectAt(idx));
441+
removing.push(objectAt(this, idx));
438442
}
439443
} else {
440444
removing = removeAmt;
@@ -482,7 +486,7 @@ export default Mixin.create(Enumerable, {
482486
lim = startIdx + addAmt;
483487

484488
for (var idx = startIdx; idx < lim; idx++) {
485-
adding.push(this.objectAt(idx));
489+
adding.push(objectAt(this, idx));
486490
}
487491
} else {
488492
adding = addAmt;
@@ -500,12 +504,12 @@ export default Mixin.create(Enumerable, {
500504
var cachedFirst = cacheFor(this, 'firstObject');
501505
var cachedLast = cacheFor(this, 'lastObject');
502506

503-
if (this.objectAt(0) !== cachedFirst) {
507+
if (objectAt(this, 0) !== cachedFirst) {
504508
propertyWillChange(this, 'firstObject');
505509
propertyDidChange(this, 'firstObject');
506510
}
507511

508-
if (this.objectAt(length - 1) !== cachedLast) {
512+
if (objectAt(this, length - 1) !== cachedLast) {
509513
propertyWillChange(this, 'lastObject');
510514
propertyDidChange(this, 'lastObject');
511515
}

packages/ember-runtime/lib/mixins/mutable_array.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ var EMPTY = [];
2121
import { get } from 'ember-metal/property_get';
2222
import EmberError from 'ember-metal/error';
2323
import { Mixin } from 'ember-metal/mixin';
24-
import EmberArray from 'ember-runtime/mixins/array';
24+
import EmberArray, { objectAt } from 'ember-runtime/mixins/array';
2525
import MutableEnumerable from 'ember-runtime/mixins/mutable_enumerable';
2626
import Enumerable from 'ember-runtime/mixins/enumerable';
2727

@@ -221,7 +221,7 @@ export default Mixin.create(EmberArray, MutableEnumerable, {
221221
return null;
222222
}
223223

224-
var ret = this.objectAt(len - 1);
224+
var ret = objectAt(this, len - 1);
225225
this.removeAt(len - 1, 1);
226226
return ret;
227227
},
@@ -246,7 +246,7 @@ export default Mixin.create(EmberArray, MutableEnumerable, {
246246
return null;
247247
}
248248

249-
var ret = this.objectAt(0);
249+
var ret = objectAt(this, 0);
250250
this.removeAt(0);
251251
return ret;
252252
},
@@ -362,7 +362,7 @@ export default Mixin.create(EmberArray, MutableEnumerable, {
362362
removeObject(obj) {
363363
var loc = get(this, 'length') || 0;
364364
while (--loc >= 0) {
365-
var curObject = this.objectAt(loc);
365+
var curObject = objectAt(this, loc);
366366

367367
if (curObject === obj) {
368368
this.removeAt(loc);

packages/ember-runtime/lib/system/array_proxy.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import EmberObject from 'ember-runtime/system/object';
1717
import MutableArray from 'ember-runtime/mixins/mutable_array';
1818
import Enumerable from 'ember-runtime/mixins/enumerable';
1919
import alias from 'ember-metal/alias';
20+
import { objectAt } from 'ember-runtime/mixins/array';
2021

2122
/**
2223
@module ember
@@ -102,7 +103,7 @@ var ArrayProxy = EmberObject.extend(MutableArray, {
102103
@private
103104
*/
104105
objectAtContent(idx) {
105-
return get(this, 'arrangedContent').objectAt(idx);
106+
return objectAt(get(this, 'arrangedContent'), idx);
106107
},
107108

108109
/**
@@ -312,7 +313,7 @@ var ArrayProxy = EmberObject.extend(MutableArray, {
312313
// Get a list of indices in original content to remove
313314
for (i = start; i < start + len; i++) {
314315
// Use arrangedContent here so we avoid confusion with objects transformed by objectAtContent
315-
indices.push(content.indexOf(arrangedContent.objectAt(i)));
316+
indices.push(content.indexOf(objectAt(arrangedContent, i)));
316317
}
317318

318319
// Replace in reverse order since indices will change

packages/ember-runtime/lib/system/each_proxy.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
propertyWillChange
1212
} from 'ember-metal/property_events';
1313
import EmptyObject from 'ember-metal/empty_object';
14+
import { objectAt } from 'ember-runtime/mixins/array';
1415

1516
/**
1617
This is the object instance returned when you get the `@each` property on an
@@ -110,7 +111,7 @@ EachProxy.prototype = {
110111

111112
function addObserverForContentKey(content, keyName, proxy, idx, loc) {
112113
while (--loc >= idx) {
113-
let item = content.objectAt(loc);
114+
let item = objectAt(content, loc);
114115
if (item) {
115116
assert('When using @each to observe the array ' + content + ', the array must return an object', typeof item === 'object');
116117
_addBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
@@ -121,7 +122,7 @@ function addObserverForContentKey(content, keyName, proxy, idx, loc) {
121122

122123
function removeObserverForContentKey(content, keyName, proxy, idx, loc) {
123124
while (--loc >= idx) {
124-
let item = content.objectAt(loc);
125+
let item = objectAt(content, loc);
125126
if (item) {
126127
_removeBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
127128
removeObserver(item, keyName, proxy, 'contentKeyDidChange');

packages/ember-runtime/tests/mixins/array_test.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { computed } from 'ember-metal/computed';
66
import { testBoth } from 'ember-metal/tests/props_helper';
77
import { ArrayTests } from 'ember-runtime/tests/suites/array';
88
import EmberObject from 'ember-runtime/system/object';
9-
import EmberArray from 'ember-runtime/mixins/array';
9+
import EmberArray, { objectAt } from 'ember-runtime/mixins/array';
1010
import { A as emberA } from 'ember-runtime/system/native_array';
1111

1212
/*
@@ -385,11 +385,16 @@ QUnit.test('modifying the array should also indicate the isDone prop itself has
385385
addObserver(each, 'isDone', function() { count++; });
386386

387387
count = 0;
388-
var item = ary.objectAt(2);
388+
var item = objectAt(ary, 2);
389389
set(item, 'isDone', !get(item, 'isDone'));
390390
equal(count, 1, '@each.isDone should have notified');
391391
});
392392

393+
QUnit.test('`objectAt` returns correct object', function() {
394+
let arr = ['first', 'second', 'third', 'fourth'];
395+
equal(objectAt(arr, 2), 'third');
396+
equal(objectAt(arr, 4), undefined);
397+
});
393398

394399
testBoth('should be clear caches for computed properties that have dependent keys on arrays that are changed after object initialization', function(get, set) {
395400
var obj = EmberObject.extend({
@@ -399,14 +404,14 @@ testBoth('should be clear caches for computed properties that have dependent key
399404
},
400405

401406
common: computed('resources.@each.common', function() {
402-
return get(get(this, 'resources').objectAt(0), 'common');
407+
return get(objectAt(get(this, 'resources'), 0), 'common');
403408
})
404409
}).create();
405410

406411
get(obj, 'resources').pushObject(EmberObject.create({ common: 'HI!' }));
407412
equal('HI!', get(obj, 'common'));
408413

409-
set(get(obj, 'resources').objectAt(0), 'common', 'BYE!');
414+
set(objectAt(get(obj, 'resources'), 0), 'common', 'BYE!');
410415
equal('BYE!', get(obj, 'common'));
411416
});
412417

@@ -428,7 +433,7 @@ testBoth('observers that contain @each in the path should fire only once the fir
428433
// Observer fires second time when new object is added
429434
get(obj, 'resources').pushObject(EmberObject.create({ common: 'HI!' }));
430435
// Observer fires third time when property on an object is changed
431-
set(get(obj, 'resources').objectAt(0), 'common', 'BYE!');
436+
set(objectAt(get(obj, 'resources'), 0), 'common', 'BYE!');
432437

433438
equal(count, 2, 'observers should only be called once');
434439
});

packages/ember-runtime/tests/suites/array/objectAt.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {SuiteModuleBuilder} from 'ember-runtime/tests/suites/suite';
2+
import { objectAt } from 'ember-runtime/mixins/array';
23

34
var suite = SuiteModuleBuilder.create();
45

@@ -11,18 +12,18 @@ suite.test('should return object at specified index', function() {
1112
var idx;
1213

1314
for (idx = 0;idx < len;idx++) {
14-
equal(obj.objectAt(idx), expected[idx], `obj.objectAt(${idx}) should match`);
15+
equal(objectAt(obj, idx), expected[idx], `obj.objectAt(${idx}) should match`);
1516
}
1617
});
1718

1819
suite.test('should return undefined when requesting objects beyond index', function() {
1920
var obj;
2021

2122
obj = this.newObject(this.newFixture(3));
22-
equal(obj.objectAt(5), undefined, 'should return undefined for obj.objectAt(5) when len = 3');
23+
equal(objectAt(obj, 5), undefined, 'should return undefined for obj.objectAt(5) when len = 3');
2324

2425
obj = this.newObject([]);
25-
equal(obj.objectAt(0), undefined, 'should return undefined for obj.objectAt(0) when len = 0');
26+
equal(objectAt(obj, 0), undefined, 'should return undefined for obj.objectAt(0) when len = 0');
2627
});
2728

2829
export default suite;

packages/ember-runtime/tests/system/array_proxy/arranged_content_test.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import run from 'ember-metal/run_loop';
22
import { computed } from 'ember-metal/computed';
33
import ArrayProxy from 'ember-runtime/system/array_proxy';
44
import { A as emberA } from 'ember-runtime/system/native_array';
5+
import { objectAt } from 'ember-runtime/mixins/array';
56

67
var array;
78

@@ -69,7 +70,7 @@ QUnit.test('nextObject - returns object at index in arrangedContent', function()
6970
});
7071

7172
QUnit.test('objectAt - returns object at index in arrangedContent', function() {
72-
equal(array.objectAt(1), 4, 'returns object at index');
73+
equal(objectAt(array, 1), 4, 'returns object at index');
7374
});
7475

7576
// Not sure if we need a specific test for it, since it's internal
@@ -217,7 +218,7 @@ QUnit.module('ArrayProxy - arrangedContent with transforms', {
217218
}).property('content.[]'),
218219

219220
objectAtContent(idx) {
220-
var obj = this.get('arrangedContent').objectAt(idx);
221+
var obj = objectAt(this.get('arrangedContent'), idx);
221222
return obj && obj.toString();
222223
}
223224
}).create({
@@ -246,7 +247,7 @@ QUnit.test('nextObject - returns object at index in arrangedContent', function()
246247
});
247248

248249
QUnit.test('objectAt - returns object at index in arrangedContent', function() {
249-
equal(array.objectAt(1), '4', 'returns object at index');
250+
equal(objectAt(array, 1), '4', 'returns object at index');
250251
});
251252

252253
// Not sure if we need a specific test for it, since it's internal

0 commit comments

Comments
 (0)