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

Use weakmap for non internal meta #12417

Closed
wants to merge 2 commits into from
Closed
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
8 changes: 4 additions & 4 deletions packages/ember-metal/lib/chains.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { warn } from 'ember-metal/debug';
import { get, normalizeTuple } from 'ember-metal/property_get';
import { meta as metaFor } from 'ember-metal/meta';
import { meta as metaFor, readMeta } from 'ember-metal/meta';
import { watchKey, unwatchKey } from 'ember-metal/watch_key';
import EmptyObject from 'ember-metal/empty_object';

Expand Down Expand Up @@ -147,7 +147,7 @@ function removeChainWatcher(obj, keyName, node) {
return;
}

let m = obj.__ember_meta__;
let m = readMeta(obj);

if (!m || !m.readableChainWatchers()) {
return;
Expand Down Expand Up @@ -195,7 +195,7 @@ function lazyGet(obj, key) {
return;
}

var meta = obj['__ember_meta__'];
var meta = readMeta(obj);

// check if object meant only to be a prototype
if (meta && meta.proto === obj) {
Expand Down Expand Up @@ -401,7 +401,7 @@ ChainNode.prototype = {

export function finishChains(obj) {
// We only create meta if we really have to
let m = obj.__ember_meta__;
let m = readMeta(obj);
if (m) {
m = metaFor(obj);

Expand Down
6 changes: 3 additions & 3 deletions packages/ember-metal/lib/computed.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { assert } from 'ember-metal/debug';
import { set } from 'ember-metal/property_set';
import { inspect } from 'ember-metal/utils';
import { meta as metaFor } from 'ember-metal/meta';
import { meta as metaFor, readMeta } from 'ember-metal/meta';
import expandProperties from 'ember-metal/expand_properties';
import EmberError from 'ember-metal/error';
import {
Expand Down Expand Up @@ -313,7 +313,7 @@ ComputedPropertyPrototype.didChange = function(obj, keyName) {
}

// don't create objects just to invalidate
let meta = obj.__ember_meta__;
let meta = readMeta(obj);
if (!meta || meta.source !== obj) {
return;
}
Expand Down Expand Up @@ -620,7 +620,7 @@ export default function computed(func) {
@public
*/
function cacheFor(obj, key) {
var meta = obj.__ember_meta__;
var meta = readMeta(obj);
var cache = meta && meta.source === obj && meta.readableCache();
var ret = cache && cache[key];

Expand Down
10 changes: 5 additions & 5 deletions packages/ember-metal/lib/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
apply,
applyStr
} from 'ember-metal/utils';
import { meta as metaFor } from 'ember-metal/meta';
import { meta as metaFor, readMeta } from 'ember-metal/meta';

import { ONCE, SUSPENDED } from 'ember-metal/meta_listeners';

Expand Down Expand Up @@ -49,7 +49,7 @@ function indexOf(array, target, method) {
}

export function accumulateListeners(obj, eventName, otherActions) {
var meta = obj['__ember_meta__'];
var meta = readMeta(obj);
if (!meta) { return; }
var actions = meta.matchingListeners(eventName);
var newActions = [];
Expand Down Expand Up @@ -201,7 +201,7 @@ export function watchedEvents(obj) {
*/
export function sendEvent(obj, eventName, params, actions) {
if (!actions) {
var meta = obj['__ember_meta__'];
var meta = readMeta(obj);
actions = meta && meta.matchingListeners(eventName);
}

Expand Down Expand Up @@ -241,7 +241,7 @@ export function sendEvent(obj, eventName, params, actions) {
@param {String} eventName
*/
export function hasListeners(obj, eventName) {
var meta = obj['__ember_meta__'];
var meta = readMeta(obj);
if (!meta) { return false; }
return meta.matchingListeners(eventName).length > 0;
}
Expand All @@ -255,7 +255,7 @@ export function hasListeners(obj, eventName) {
*/
export function listenersFor(obj, eventName) {
var ret = [];
var meta = obj['__ember_meta__'];
var meta = readMeta(obj);
var actions = meta && meta.matchingListeners(eventName);

if (!actions) { return ret; }
Expand Down
28 changes: 24 additions & 4 deletions packages/ember-metal/lib/meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ var EMBER_META_PROPERTY = {

// Placeholder for non-writable metas.
export var EMPTY_META = new Meta(null);

var weakMeta = self.WeakMap && new self.WeakMap();
/**
Retrieves the meta hash for an object. If `writable` is true ensures the
hash is writable for this object as well.
Expand All @@ -318,7 +318,8 @@ export var EMPTY_META = new Meta(null);
@return {Object} the meta hash for an object
*/
export function meta(obj, writable) {
var ret = obj.__ember_meta__;
var ret = readMeta(obj);

if (writable === false) {
return ret || EMPTY_META;
}
Expand All @@ -335,14 +336,33 @@ export function meta(obj, writable) {

// if `null` already, just set it to the new value
// otherwise define property first
if (obj.__ember_meta__ !== null) {
if (obj.__ember_meta__ === null) {
obj.__ember_meta__ = ret;
} else if (weakMeta) {
weakMeta.set(obj, ret);
} else {
if (obj.__defineNonEnumerable) {
obj.__defineNonEnumerable(EMBER_META_PROPERTY);
} else {
Object.defineProperty(obj, '__ember_meta__', META_DESC);
}
obj.__ember_meta__ = ret;
}
obj.__ember_meta__ = ret;


return ret;
}

export function readMeta(obj) {
if (obj.__ember_meta__) {
return obj.__ember_meta__;
} else if (weakMeta) {
return weakMeta.get(obj);
}
}


export function deleteMeta(obj) {
if (obj.__ember_meta__) { obj.__ember_meta__ = null; }
else if (weakMeta) { weakMeta.delete(obj); }
}
5 changes: 3 additions & 2 deletions packages/ember-metal/lib/mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
removeListener
} from 'ember-metal/events';
import { isStream } from 'ember-metal/streams/utils';
import { readMeta } from 'ember-metal/meta';

function ROOT() {}
ROOT.__hasSuper = false;
Expand Down Expand Up @@ -604,7 +605,7 @@ function _detect(curMixin, targetMixin, seen) {
MixinPrototype.detect = function(obj) {
if (!obj) { return false; }
if (obj instanceof Mixin) { return _detect(obj, this, {}); }
var m = obj.__ember_meta__;
var m = readMeta(obj);
if (!m) { return false; }
return !!m.peekMixins(guidFor(this));
};
Expand Down Expand Up @@ -645,7 +646,7 @@ MixinPrototype.keys = function() {
// returns the mixins currently applied to the specified object
// TODO: Make Ember.mixin
Mixin.mixins = function(obj) {
var m = obj['__ember_meta__'];
var m = readMeta(obj);
var ret = [];
if (!m) { return ret; }

Expand Down
4 changes: 2 additions & 2 deletions packages/ember-metal/lib/properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import { assert } from 'ember-metal/debug';
import isEnabled from 'ember-metal/features';
import { meta as metaFor } from 'ember-metal/meta';
import { meta as metaFor, readMeta } from 'ember-metal/meta';
import { overrideChains } from 'ember-metal/property_events';
// ..........................................................
// DESCRIPTOR
Expand Down Expand Up @@ -33,7 +33,7 @@ export function MANDATORY_SETTER_FUNCTION(name) {

export function DEFAULT_GETTER_FUNCTION(name) {
return function GETTER_FUNCTION() {
var meta = this['__ember_meta__'];
var meta = readMeta(this);
return meta && meta.peekValues(name);
};
}
Expand Down
5 changes: 3 additions & 2 deletions packages/ember-metal/lib/property_events.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from 'ember-metal/events';
import ObserverSet from 'ember-metal/observer_set';
import { symbol } from 'ember-metal/utils';
import { readMeta } from 'ember-metal/meta';

export let PROPERTY_DID_CHANGE = symbol('PROPERTY_DID_CHANGE');

Expand Down Expand Up @@ -35,7 +36,7 @@ var deferred = 0;
@private
*/
function propertyWillChange(obj, keyName) {
var m = obj['__ember_meta__'];
var m = readMeta(obj);
var watching = (m && m.peekWatching(keyName) > 0) || keyName === 'length';
var proto = m && m.proto;
var possibleDesc = obj[keyName];
Expand Down Expand Up @@ -75,7 +76,7 @@ function propertyWillChange(obj, keyName) {
@private
*/
function propertyDidChange(obj, keyName) {
var m = obj['__ember_meta__'];
var m = readMeta(obj);
var watching = (m && m.peekWatching(keyName) > 0) || keyName === 'length';
var proto = m && m.proto;
var possibleDesc = obj[keyName];
Expand Down
5 changes: 4 additions & 1 deletion packages/ember-metal/lib/property_get.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import {
isPath,
hasThis as pathHasThis
} from 'ember-metal/path_cache';
import {
readMeta
} from 'ember-metal/meta';

var FIRST_KEY = /^([^\.]+)/;

Expand Down Expand Up @@ -57,7 +60,7 @@ export function get(obj, keyName) {
return obj;
}

var meta = obj['__ember_meta__'];
var meta = readMeta(obj);
var possibleDesc = obj[keyName];
var desc = (possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor) ? possibleDesc : undefined;
var ret;
Expand Down
3 changes: 2 additions & 1 deletion packages/ember-metal/lib/property_set.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
isPath,
hasThis as pathHasThis
} from 'ember-metal/path_cache';
import { readMeta } from 'ember-metal/meta';

/**
Sets the value of a property on an object, respecting computed properties
Expand All @@ -38,7 +39,7 @@ export function set(obj, keyName, value, tolerant) {

var meta, possibleDesc, desc;
if (obj) {
meta = obj['__ember_meta__'];
meta = readMeta(obj);
possibleDesc = obj[keyName];
desc = (possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor) ? possibleDesc : undefined;
}
Expand Down
7 changes: 4 additions & 3 deletions packages/ember-metal/lib/watching.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
import {
isPath
} from 'ember-metal/path_cache';
import { readMeta, deleteMeta } from 'ember-metal/meta';

/**
Starts watching a property on an object. Whenever the property changes,
Expand Down Expand Up @@ -45,7 +46,7 @@ function watch(obj, _keyPath, m) {
export { watch };

export function isWatching(obj, key) {
var meta = obj['__ember_meta__'];
var meta = readMeta(obj);
return (meta && meta.peekWatching(key)) > 0;
}

Expand Down Expand Up @@ -75,11 +76,11 @@ var NODE_STACK = [];
@private
*/
export function destroy(obj) {
var meta = obj['__ember_meta__'];
var meta = readMeta(obj);
var node, nodes, key, nodeObject;

if (meta) {
obj['__ember_meta__'] = null;
deleteMeta(obj);
// remove chainWatchers to remove circular references that would prevent GC
node = meta.readableChains();
if (node) {
Expand Down
3 changes: 2 additions & 1 deletion packages/ember-metal/tests/chains_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { finishChains } from 'ember-metal/chains';
import { defineProperty } from 'ember-metal/properties';
import computed from 'ember-metal/computed';
import { propertyDidChange } from 'ember-metal/property_events';
import { readMeta } from 'ember-metal/meta';
QUnit.module('Chains');

QUnit.test('finishChains should properly copy chains from prototypes to instances', function() {
Expand All @@ -14,7 +15,7 @@ QUnit.test('finishChains should properly copy chains from prototypes to instance

var childObj = Object.create(obj);
finishChains(childObj);
ok(obj['__ember_meta__'].readableChains() !== childObj['__ember_meta__'].readableChains(), 'The chains object is copied');
ok(readMeta(obj).readableChains() !== readMeta(childObj).readableChains(), 'The chains object is copied');
});


Expand Down
2 changes: 1 addition & 1 deletion packages/ember-runtime/lib/system/each_proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import EmptyObject from 'ember-metal/empty_object';
function EachProxy(content) {
this._content = content;
this._keys = undefined;
this.__ember_meta__ = undefined;
this.__ember_meta__ = null;
}

EachProxy.prototype = {
Expand Down
5 changes: 3 additions & 2 deletions packages/ember-runtime/tests/system/object/destroy_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from 'ember-metal/property_events';
import { testBoth } from 'ember-metal/tests/props_helper';
import EmberObject from 'ember-runtime/system/object';
import { readMeta } from 'ember-metal/meta';

QUnit.module('ember-runtime/system/object/destroy_test');

Expand All @@ -18,13 +19,13 @@ testBoth('should schedule objects to be destroyed at the end of the run loop', f

run(function() {
obj.destroy();
meta = obj['__ember_meta__'];
meta = readMeta(obj);
ok(meta, 'meta is not destroyed immediately');
ok(get(obj, 'isDestroying'), 'object is marked as destroying immediately');
ok(!get(obj, 'isDestroyed'), 'object is not destroyed immediately');
});

meta = obj['__ember_meta__'];
meta = readMeta(obj);
ok(!meta, 'meta is destroyed after run loop finishes');
ok(get(obj, 'isDestroyed'), 'object is destroyed after run loop finishes');
});
Expand Down