-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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 canary] Meta refactor #11966
Changes from 36 commits
a5dcce8
8133291
3044547
ab25153
807b963
31c16f0
4bb9009
d885f23
542765b
a4c9dd3
68895ec
aab8f9a
0b96990
bbfb0e7
c40512a
bab0092
9b51c9e
1fd3eb5
a3f86cc
93743c1
d51a492
f216afc
a4a4854
2d70d56
d748879
dbc712c
8886eb7
45d73c1
26008e0
c4b3bce
71ebf9c
84a0a50
7b5fcc0
c64b316
09218cf
714f0b8
580a40a
a64e211
b6b0739
584fc73
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,7 @@ | ||
import Ember from 'ember-metal/core'; | ||
import { set } from 'ember-metal/property_set'; | ||
import { | ||
meta, | ||
inspect | ||
} from 'ember-metal/utils'; | ||
import { inspect } from 'ember-metal/utils'; | ||
import { meta } from 'ember-metal/meta'; | ||
import expandProperties from 'ember-metal/expand_properties'; | ||
import EmberError from 'ember-metal/error'; | ||
import { | ||
|
@@ -266,9 +264,10 @@ ComputedPropertyPrototype.didChange = function(obj, keyName) { | |
// _suspended is set via a CP.set to ensure we don't clear | ||
// the cached value set by the setter | ||
if (this._cacheable && this._suspended !== obj) { | ||
var meta = metaFor(obj); | ||
if (meta.cache && meta.cache[keyName] !== undefined) { | ||
meta.cache[keyName] = undefined; | ||
let meta = metaFor(obj); | ||
let cache = meta.readableCache(); | ||
if (cache && cache[keyName] !== undefined) { | ||
cache[keyName] = undefined; | ||
removeDependentKeys(this, obj, keyName, meta); | ||
} | ||
} | ||
|
@@ -305,9 +304,9 @@ ComputedPropertyPrototype.get = function(obj, keyName) { | |
var ret, cache, meta; | ||
if (this._cacheable) { | ||
meta = metaFor(obj); | ||
cache = meta.cache; | ||
cache = meta.writableCache(); | ||
|
||
var result = cache && cache[keyName]; | ||
var result = cache[keyName]; | ||
|
||
if (result === UNDEFINED) { | ||
return undefined; | ||
|
@@ -316,18 +315,16 @@ ComputedPropertyPrototype.get = function(obj, keyName) { | |
} | ||
|
||
ret = this._getter.call(obj, keyName); | ||
cache = meta.cache; | ||
if (!cache) { | ||
cache = meta.cache = {}; | ||
} | ||
|
||
if (ret === undefined) { | ||
cache[keyName] = UNDEFINED; | ||
} else { | ||
cache[keyName] = ret; | ||
} | ||
|
||
if (meta.chainWatchers) { | ||
meta.chainWatchers.revalidate(keyName); | ||
let chainWatchers = meta.readableChainWatchers(); | ||
if (chainWatchers) { | ||
chainWatchers.revalidate(keyName); | ||
} | ||
addDependentKeys(this, obj, keyName, meta); | ||
} else { | ||
|
@@ -401,7 +398,7 @@ ComputedPropertyPrototype._set = function computedPropertySet(obj, keyName, valu | |
var cacheable = this._cacheable; | ||
var setter = this._setter; | ||
var meta = metaFor(obj, cacheable); | ||
var cache = meta.cache; | ||
var cache = meta.readableCache(); | ||
var hadCachedValue = false; | ||
|
||
var cachedValue, ret; | ||
|
@@ -427,7 +424,7 @@ ComputedPropertyPrototype._set = function computedPropertySet(obj, keyName, valu | |
|
||
if (hadCachedValue && cachedValue === ret) { return; } | ||
|
||
var watched = meta.watching[keyName]; | ||
var watched = meta.peekWatching(keyName); | ||
if (watched) { | ||
propertyWillChange(obj, keyName); | ||
} | ||
|
@@ -441,7 +438,7 @@ ComputedPropertyPrototype._set = function computedPropertySet(obj, keyName, valu | |
addDependentKeys(this, obj, keyName, meta); | ||
} | ||
if (!cache) { | ||
cache = meta.cache = {}; | ||
cache = meta.writableCache(); | ||
} | ||
if (ret === undefined) { | ||
cache[keyName] = UNDEFINED; | ||
|
@@ -460,13 +457,13 @@ ComputedPropertyPrototype._set = function computedPropertySet(obj, keyName, valu | |
/* called before property is overridden */ | ||
ComputedPropertyPrototype.teardown = function(obj, keyName) { | ||
var meta = metaFor(obj); | ||
|
||
if (meta.cache) { | ||
if (keyName in meta.cache) { | ||
let cache = meta.readableCache(); | ||
if (cache) { | ||
if (keyName in cache) { | ||
removeDependentKeys(this, obj, keyName, meta); | ||
} | ||
|
||
if (this._cacheable) { delete meta.cache[keyName]; } | ||
if (this._cacheable) { delete cache[keyName]; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. given the above it my be worth investigating |
||
} | ||
|
||
return null; // no value to restore | ||
|
@@ -560,7 +557,7 @@ export default function computed(func) { | |
*/ | ||
function cacheFor(obj, key) { | ||
var meta = obj['__ember_meta__']; | ||
var cache = meta && meta.cache; | ||
var cache = meta && meta.readableCache(); | ||
var ret = cache && cache[key]; | ||
|
||
if (ret === UNDEFINED) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// This exists because `Object.create(null)` is absurdly slow compared | ||
// to `new EmptyObject()`. In either case, you want a null prototype | ||
// when you're treating the object instances as arbitrary dictionaries | ||
// and don't want your keys colliding with build-in methods on the | ||
// default object prototype. | ||
|
||
var proto = Object.create(null, { | ||
// without this, we will always still end up with (new | ||
// EmptyObject()).constructor === Object | ||
constructor: { | ||
value: undefined, | ||
enumerable: false, | ||
writable: true | ||
} | ||
}); | ||
|
||
function EmptyObject() {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. slightly more concise version is possible export default function EmptyObject() {
}
EmptyObject.prototype = null |
||
EmptyObject.prototype = proto; | ||
export default EmptyObject; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if I recall, the cache will never have an undefined member representing the value of undefined, rather it will use the UNDEFINED sentinel value. This means, we can likely just do (the unfortunately faster)
if (cache[keyName] !== undefined)