Skip to content

Commit

Permalink
Merge pull request #15040 from chadhietala/remove-array-cycle
Browse files Browse the repository at this point in the history
Remove cycle mixins/array -> system/each_proxy
  • Loading branch information
rwjblue authored Mar 20, 2017
2 parents 1d3b108 + 2e58688 commit f0ff486
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 132 deletions.
127 changes: 123 additions & 4 deletions packages/ember-runtime/lib/mixins/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ import Ember, { // ES6TODO: Ember.A
addListener,
removeListener,
sendEvent,
hasListeners
hasListeners,
_addBeforeObserver,
_removeBeforeObserver,
addObserver,
removeObserver
} from 'ember-metal';
import { deprecate } from 'ember-debug';

import { deprecate, assert } from 'ember-debug';
import Enumerable from './enumerable';
import EachProxy from '../system/each_proxy';

function arrayObserversHelper(obj, target, opts, operation, notify) {
let willChange = (opts && opts.willChange) || 'arrayWillChange';
Expand Down Expand Up @@ -626,4 +628,121 @@ const ArrayMixin = Mixin.create(Enumerable, {
}).volatile().readOnly()
});

/**
This is the object instance returned when you get the `@each` property on an
array. It uses the unknownProperty handler to automatically create
EachArray instances for property names.
@class EachProxy
@private
*/
function EachProxy(content) {
this._content = content;
this._keys = undefined;
this.__ember_meta__ = null;
}

EachProxy.prototype = {
__defineNonEnumerable(property) {
this[property.name] = property.descriptor.value;
},

// ..........................................................
// ARRAY CHANGES
// Invokes whenever the content array itself changes.

arrayWillChange(content, idx, removedCnt, addedCnt) {
let keys = this._keys;
let lim = removedCnt > 0 ? idx + removedCnt : -1;
for (let key in keys) {
if (lim > 0) {
removeObserverForContentKey(content, key, this, idx, lim);
}
propertyWillChange(this, key);
}
},

arrayDidChange(content, idx, removedCnt, addedCnt) {
let keys = this._keys;
let lim = addedCnt > 0 ? idx + addedCnt : -1;
for (let key in keys) {
if (lim > 0) {
addObserverForContentKey(content, key, this, idx, lim);
}
propertyDidChange(this, key);
}
},

// ..........................................................
// LISTEN FOR NEW OBSERVERS AND OTHER EVENT LISTENERS
// Start monitoring keys based on who is listening...

willWatchProperty(property) {
this.beginObservingContentKey(property);
},

didUnwatchProperty(property) {
this.stopObservingContentKey(property);
},

// ..........................................................
// CONTENT KEY OBSERVING
// Actual watch keys on the source content.

beginObservingContentKey(keyName) {
let keys = this._keys;
if (!keys) {
keys = this._keys = Object.create(null);
}

if (!keys[keyName]) {
keys[keyName] = 1;
let content = this._content;
let len = get(content, 'length');

addObserverForContentKey(content, keyName, this, 0, len);
} else {
keys[keyName]++;
}
},

stopObservingContentKey(keyName) {
let keys = this._keys;
if (keys && (keys[keyName] > 0) && (--keys[keyName] <= 0)) {
let content = this._content;
let len = get(content, 'length');

removeObserverForContentKey(content, keyName, this, 0, len);
}
},

contentKeyWillChange(obj, keyName) {
propertyWillChange(this, keyName);
},

contentKeyDidChange(obj, keyName) {
propertyDidChange(this, keyName);
}
};

function addObserverForContentKey(content, keyName, proxy, idx, loc) {
while (--loc >= idx) {
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');
addObserver(item, keyName, proxy, 'contentKeyDidChange');
}
}
}

function removeObserverForContentKey(content, keyName, proxy, idx, loc) {
while (--loc >= idx) {
let item = objectAt(content, loc);
if (item) {
_removeBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
removeObserver(item, keyName, proxy, 'contentKeyDidChange');
}
}
}

export default ArrayMixin;
128 changes: 0 additions & 128 deletions packages/ember-runtime/lib/system/each_proxy.js

This file was deleted.

0 comments on commit f0ff486

Please sign in to comment.