Skip to content
Browse files

Cache computation of Base/BaseCore's `_ATTR_CFG_HASH`.

A Base/BaseCore-based class will now compute its `_ATTR_CFG_HASH` on
demand, when it is needed. If an extension is mixed in via
`Y.Base.mix()`, then the cached hash will be nulled-out.
  • Loading branch information...
1 parent a4cc1a7 commit 755e200df6882e63cafd5c3b63b15d3e0076e5e1 @ericf committed Oct 12, 2012
Showing with 71 additions and 22 deletions.
  1. +14 −2 src/base/js/BaseBuild.js
  2. +32 −20 src/base/js/BaseCore.js
  3. +25 −0 src/base/tests/unit/assets/base-tests.js
View
16 src/base/js/BaseBuild.js
@@ -25,6 +25,18 @@
}
}
+ // Utility function used in `_buildCfg` to aggregate `_ATTR_CFG` array
+ // values from the sender constructor into a new array on reciver's
+ // constructor, and clear the cached hash.
+ function attrCfgAggregator(prop, r, s) {
+ if (s._ATTR_CFG) {
+ arrayAggregator.apply(null, arguments);
+
+ // Clear cached hash.
+ r._ATTR_CFG_HASH = null;
+ }
+ }
+
// Utility function used in `_buildCfg` to aggregate ATTRS configs from one
// the sender constructor to the reciver constructor.
function attrsAggregator(prop, r, s) {
@@ -421,7 +433,7 @@
BaseCore._buildCfg = {
custom: {
ATTRS : attrsAggregator,
- _ATTR_CFG : arrayAggregator,
+ _ATTR_CFG : attrCfgAggregator,
_NON_ATTRS_CFG: arrayAggregator
},
@@ -432,7 +444,7 @@
Base._buildCfg = {
custom: {
ATTRS : attrsAggregator,
- _ATTR_CFG : arrayAggregator,
+ _ATTR_CFG : attrCfgAggregator,
_NON_ATTRS_CFG: arrayAggregator
},
View
52 src/base/js/BaseCore.js
@@ -308,18 +308,6 @@
return this._attrs;
},
-
- /**
- * Utility method to define the attribute hash used to filter/whitelist property mixes for
- * this class.
- *
- * @method _getAttrCfgHash
- * @private
- */
- _getAttrCfgHash: function() {
- return this._attrCfgHash;
- },
-
/**
* A helper method used when processing ATTRS across the class hierarchy during
* initialization. Returns a disposable object with the attributes defined for
@@ -391,16 +379,21 @@
* @private
*/
_initHierarchyData : function() {
- var c = this.constructor,
+ var ctor = this.constructor,
+ c,
i,
l,
attrCfg,
- attrCfgHash = {},
+ attrCfgHash,
+ needsAttrCfgHash = !ctor._ATTR_CFG_HASH,
nonAttrsCfg,
nonAttrs = (this._allowAdHocAttrs) ? {} : null,
classes = [],
attrs = [];
+ // Start with `this` instance's constructor.
+ c = ctor;
+
while (c) {
// Add to classes
classes[classes.length] = c;
@@ -411,10 +404,14 @@
}
// Aggregate ATTR cfg whitelist.
- attrCfg = c._ATTR_CFG;
- if (attrCfg) {
- for (i = 0, l = attrCfg.length; i < l; i += 1) {
- attrCfgHash[attrCfg[i]] = true;
+ if (needsAttrCfgHash) {
+ attrCfg = c._ATTR_CFG;
+ attrCfgHash = attrCfgHash || {};
+
+ if (attrCfg) {
+ for (i = 0, l = attrCfg.length; i < l; i += 1) {
+ attrCfgHash[attrCfg[i]] = true;
+ }
}
}
@@ -430,13 +427,28 @@
c = c.superclass ? c.superclass.constructor : null;
}
+ // Cache computed `_ATTR_CFG_HASH` on the constructor.
+ if (needsAttrCfgHash) {
+ ctor._ATTR_CFG_HASH = attrCfgHash;
+ }
+
this._classes = classes;
- this._attrCfgHash = attrCfgHash;
this._nonAttrs = nonAttrs;
this._attrs = this._aggregateAttrs(attrs);
},
/**
+ * Utility method to define the attribute hash used to filter/whitelist property mixes for
+ * this class.
+ *
+ * @method _attrCfgHash
+ * @private
+ */
+ _attrCfgHash: function() {
+ return this.constructor._ATTR_CFG_HASH;
+ },
+
+ /**
* A helper method, used by _initHierarchyData to aggregate
* attribute configuration across the instances class hierarchy.
*
@@ -458,7 +470,7 @@
path,
i,
clone,
- cfgPropsHash = this._getAttrCfgHash(),
+ cfgPropsHash = this._attrCfgHash(),
aggAttr,
aggAttrs = {};
View
25 src/base/tests/unit/assets/base-tests.js
@@ -1509,6 +1509,31 @@ YUI.add('base-tests', function(Y) {
Y.Assert.areSame('BAZ', foo.get('bar'));
Y.Assert.areSame(1, calls);
+ },
+
+ "test:base-core-subclass-with-mix-of-base-events-ext": function () {
+ var Foo, foo;
+
+ Foo = Y.Base.create('foo', Y.BaseCore, []);
+
+ // `null` or `undefined`.
+ Y.Assert.isTrue(Foo._ATTR_CFG_HASH == undefined);
+
+ foo = new Foo();
+
+ Y.Assert.isNotNull(Foo._ATTR_CFG_HASH);
+ Y.Assert.isUndefined(Foo._ATTR_CFG_HASH.broadcast);
+
+ Y.Base.mix(Foo, [Y.BaseEvents]);
+
+ // Check that cached hash was cleared.
+ // `null` or `undefined`.
+ Y.Assert.isTrue(Foo._ATTR_CFG_HASH == undefined);
+
+ foo = new Foo();
+
+ Y.Assert.isNotNull(Foo._ATTR_CFG_HASH);
+ Y.Assert.isNotUndefined(Foo._ATTR_CFG_HASH.broadcast);
}
}));

0 comments on commit 755e200

Please sign in to comment.
Something went wrong with that request. Please try again.