Skip to content

Commit

Permalink
Merge pull request #15150 from emberjs/cleanup-proxy
Browse files Browse the repository at this point in the history
[BUGFIX beta] [PERF] Cleanup Proxy
  • Loading branch information
stefanpenner authored Apr 24, 2017
2 parents b80407b + b45ee9d commit e36d849
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 50 deletions.
8 changes: 8 additions & 0 deletions packages/ember-metal/lib/meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@ export class Meta {
return this.proto !== obj;
}

setTag(tag) {
this._tag = tag;
}

getTag(tag) {
return this._tag;
}

destroy() {
if (this.isMetaDestroyed()) { return; }

Expand Down
45 changes: 20 additions & 25 deletions packages/ember-metal/lib/property_events.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@ function propertyWillChange(obj, keyName, _meta) {
*/
function propertyDidChange(obj, keyName, _meta) {
let meta = _meta || peekMeta(obj);
let hasMeta = !!meta;

if (meta && !meta.isInitialized(obj)) {
if (hasMeta && !meta.isInitialized(obj)) {
return;
}

let watching = meta && meta.peekWatching(keyName) > 0;
let possibleDesc = obj[keyName];
let desc = (possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor) ? possibleDesc : undefined;

Expand All @@ -97,23 +97,23 @@ function propertyDidChange(obj, keyName, _meta) {
desc.didChange(obj, keyName);
}

if (watching) {
if (meta.hasDeps(keyName)) {
if (hasMeta && meta.peekWatching(keyName) > 0) {
if (meta.hasDeps(keyName) && !meta.isSourceDestroying()) {
dependentKeysDidChange(obj, keyName, meta);
}

chainsDidChange(obj, keyName, meta, false);
notifyObservers(obj, keyName, meta);
}


if (obj[PROPERTY_DID_CHANGE]) {
obj[PROPERTY_DID_CHANGE](keyName);
}

if (meta && meta.isSourceDestroying()) { return; }

markObjectAsDirty(meta, keyName);
if (hasMeta) {
if (meta.isSourceDestroying()) { return; }
markObjectAsDirty(meta, keyName);
}

if (EMBER_GLIMMER_DETECT_BACKTRACKING_RERENDER || EMBER_GLIMMER_ALLOW_BACKTRACKING_RERENDER) {
assertNotRendered(obj, keyName, meta);
Expand All @@ -123,9 +123,8 @@ function propertyDidChange(obj, keyName, _meta) {
let WILL_SEEN, DID_SEEN;
// called whenever a property is about to change to clear the cache of any dependent keys (and notify those properties of changes, etc...)
function dependentKeysWillChange(obj, depKey, meta) {
if (meta && meta.isSourceDestroying()) { return; }

if (meta && meta.hasDeps(depKey)) {
if (meta.isSourceDestroying()) { return; }
if (meta.hasDeps(depKey)) {
let seen = WILL_SEEN;
let top = !seen;

Expand All @@ -143,21 +142,17 @@ function dependentKeysWillChange(obj, depKey, meta) {

// called whenever a property has just changed to update dependent keys
function dependentKeysDidChange(obj, depKey, meta) {
if (meta && meta.isSourceDestroying()) { return; }
let seen = DID_SEEN;
let top = !seen;

if (meta && meta.hasDeps(depKey)) {
let seen = DID_SEEN;
let top = !seen;

if (top) {
seen = DID_SEEN = {};
}
if (top) {
seen = DID_SEEN = {};
}

iterDeps(propertyDidChange, obj, depKey, seen, meta);
iterDeps(propertyDidChange, obj, depKey, seen, meta);

if (top) {
DID_SEEN = null;
}
if (top) {
DID_SEEN = null;
}
}

Expand Down Expand Up @@ -258,7 +253,7 @@ function changeProperties(callback, binding) {
}

function notifyBeforeObservers(obj, keyName, meta) {
if (meta && meta.isSourceDestroying()) { return; }
if (meta.isSourceDestroying()) { return; }

let eventName = `${keyName}:before`;
let listeners, added;
Expand All @@ -272,7 +267,7 @@ function notifyBeforeObservers(obj, keyName, meta) {
}

function notifyObservers(obj, keyName, meta) {
if (meta && meta.isSourceDestroying()) { return; }
if (meta.isSourceDestroying()) { return; }

let eventName = `${keyName}:change`;
let listeners;
Expand Down
28 changes: 15 additions & 13 deletions packages/ember-metal/lib/tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,18 @@ function makeTag() {
}

export function tagForProperty(object, propertyKey, _meta) {
if (isProxy(object)) {
return tagFor(object, _meta);
if (typeof object !== 'object' || object === null) { return CONSTANT_TAG; }

let meta = _meta || metaFor(object);
if (meta.isProxy()) {
return tagFor(object, meta);
}

if (typeof object === 'object' && object) {
let meta = _meta || metaFor(object);
let tags = meta.writableTags();
let tag = tags[propertyKey];
if (tag) { return tag; }
let tags = meta.writableTags();
let tag = tags[propertyKey];
if (tag) { return tag; }

return tags[propertyKey] = makeTag();
} else {
return CONSTANT_TAG;
}
return tags[propertyKey] = makeTag();
}

export function tagFor(object, _meta) {
Expand All @@ -40,19 +38,23 @@ export function tagFor(object, _meta) {
}

export function markObjectAsDirty(meta, propertyKey) {
let objectTag = meta && meta.readableTag();
let objectTag = meta.readableTag();

if (objectTag) {
objectTag.dirty();
}

let tags = meta && meta.readableTags();
let tags = meta.readableTags();
let propertyTag = tags && tags[propertyKey];

if (propertyTag) {
propertyTag.dirty();
}

if (propertyKey === 'content' && meta.isProxy()) {
meta.getTag().contentDidChange();
}

if (objectTag || propertyTag) {
ensureRunloop();
}
Expand Down
17 changes: 5 additions & 12 deletions packages/ember-runtime/lib/mixins/-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,22 +84,13 @@ export default Mixin.create({

init() {
this._super(...arguments);
meta(this).setProxy();
let m = meta(this);
m.setProxy();
m.setTag(new ProxyTag(this));
},

_initializeTag: on('init', function() {
meta(this)._tag = new ProxyTag(this);
}),

_contentDidChange: observer('content', function() {
assert('Can\'t set Proxy\'s content to itself', get(this, 'content') !== this);
tagFor(this).contentDidChange();
}),

isTruthy: bool('content'),

_debugContainerKey: null,

willWatchProperty(key) {
let contentKey = `content.${key}`;
_addBeforeObserver(this, contentKey, null, contentPropertyWillChange);
Expand All @@ -126,6 +117,7 @@ export default Mixin.create({

setUnknownProperty(key, value) {
let m = meta(this);

if (m.proto === this) {
// if marked as prototype then just defineProperty
// rather than delegate
Expand All @@ -141,6 +133,7 @@ export default Mixin.create({
!this.isController,
{ id: 'ember-runtime.controller-proxy', until: '3.0.0' }
);

return set(content, key, value);
}
});

0 comments on commit e36d849

Please sign in to comment.