NOBUG: Fixed file access permissions
[moodle.git] / lib / yuilib / 3.13.0 / base-core / base-core-debug.js
blob09a928d749d4a6475dcfdb6f9cac9ede09d73ac7
1 /*
2 YUI 3.13.0 (build 508226d)
3 Copyright 2013 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
6 */
8 YUI.add('base-core', function (Y, NAME) {
10     /**
11      * The base module provides the Base class, which objects requiring attribute and custom event support can extend.
12      * The module also provides two ways to reuse code - It augments Base with the Plugin.Host interface which provides
13      * plugin support and also provides the BaseCore.build method which provides a way to build custom classes using extensions.
14      *
15      * @module base
16      */
18     /**
19      * <p>The base-core module provides the BaseCore class, the lightest version of Base,
20      * which provides Base's basic lifecycle management and ATTRS construction support,
21      * but doesn't fire init/destroy or attribute change events.</p>
22      *
23      * <p>It mixes in AttributeCore, which is the lightest version of Attribute</p>
24      *
25      * @module base
26      * @submodule base-core
27      */
28     var O = Y.Object,
29         L = Y.Lang,
30         DOT = ".",
31         INITIALIZED = "initialized",
32         DESTROYED = "destroyed",
33         INITIALIZER = "initializer",
34         VALUE = "value",
35         OBJECT_CONSTRUCTOR = Object.prototype.constructor,
36         DEEP = "deep",
37         SHALLOW = "shallow",
38         DESTRUCTOR = "destructor",
40         AttributeCore = Y.AttributeCore,
42         _wlmix = function(r, s, wlhash) {
43             var p;
44             for (p in s) {
45                 if(wlhash[p]) {
46                     r[p] = s[p];
47                 }
48             }
49             return r;
50         };
52     /**
53      * The BaseCore class, is the lightest version of Base, and provides Base's
54      * basic lifecycle management and ATTRS construction support, but doesn't
55      * fire init/destroy or attribute change events.
56      *
57      * BaseCore also handles the chaining of initializer and destructor methods across
58      * the hierarchy as part of object construction and destruction. Additionally, attributes
59      * configured through the static <a href="#property_BaseCore.ATTRS">ATTRS</a>
60      * property for each class in the hierarchy will be initialized by BaseCore.
61      *
62      * Classes which require attribute support, but don't intend to use/expose attribute
63      * change events can extend BaseCore instead of Base for optimal kweight and
64      * runtime performance.
65      *
66      * **3.11.0 BACK COMPAT NOTE FOR COMPONENT DEVELOPERS**
67      *
68      * Prior to version 3.11.0, ATTRS would get added a class at a time. That is:
69      *
70      * <pre>
71      *    for each (class in the hierarchy) {
72      *       Call the class Extension constructors.
73      *
74      *       Add the class ATTRS.
75      *
76      *       Call the class initializer
77      *       Call the class Extension initializers.
78      *    }
79      * </pre>
80      *
81      * As of 3.11.0, ATTRS from all classes in the hierarchy are added in one `addAttrs` call
82      * before **any** initializers are called. That is, the flow becomes:
83      *
84      * <pre>
85      *    for each (class in the hierarchy) {
86      *       Call the class Extension constructors.
87      *    }
88      *
89      *    Add ATTRS for all classes
90      *
91      *    for each (class in the hierarchy) {
92      *       Call the class initializer.
93      *       Call the class Extension initializers.
94      *    }
95      * </pre>
96      *
97      * Adding all ATTRS at once fixes subtle edge-case issues with subclass ATTRS overriding
98      * superclass `setter`, `getter` or `valueFn` definitions and being unable to get/set attributes
99      * defined by the subclass. It also leaves us with a cleaner order of operation flow moving
100      * forward.
101      *
102      * However, it may require component developers to upgrade their components, for the following
103      * scenarios:
104      *
105      * 1. It impacts components which may have `setter`, `getter` or `valueFn` code which
106      * expects a superclass' initializer to have run.
107      *
108      * This is expected to be rare, but to support it, Base now supports a `_preAddAttrs()`, method
109      * hook (same signature as `addAttrs`). Components can implement this method on their prototype
110      * for edge cases which do require finer control over the order in which attributes are added
111      * (see widget-htmlparser for example).
112      *
113      * 2. Extension developers may need to move code from Extension constructors to `initializer`s
114      *
115      * Older extensions, which were written before `initializer` support was added, had a lot of
116      * initialization code in their constructors. For example, code which acccessed superclass
117      * attributes. With the new flow this code would not be able to see attributes. The recommendation
118      * is to move this initialization code to an `initializer` on the Extension, which was the
119      * recommendation for anything created after `initializer` support for Extensions was added.
120      *
121      * @class BaseCore
122      * @constructor
123      * @uses AttributeCore
124      * @param {Object} cfg Object with configuration property name/value pairs.
125      * The object can be used to provide initial values for the objects published
126      * attributes.
127      */
128     function BaseCore(cfg) {
129         if (!this._BaseInvoked) {
130             this._BaseInvoked = true;
132             Y.log('constructor called', 'life', 'base');
133             this._initBase(cfg);
134         }
135         else { Y.log('Based constructor called more than once. Ignoring duplicate calls', 'life', 'base'); }
136     }
138     /**
139      * The list of properties which can be configured for each attribute
140      * (e.g. setter, getter, writeOnce, readOnly etc.)
141      *
142      * @property _ATTR_CFG
143      * @type Array
144      * @static
145      * @private
146      */
147     BaseCore._ATTR_CFG = AttributeCore._ATTR_CFG.concat("cloneDefaultValue");
149     /**
150      * The array of non-attribute configuration properties supported by this class.
151      *
152      * For example `BaseCore` defines a "plugins" configuration property which
153      * should not be set up as an attribute. This property is primarily required so
154      * that when <a href="#property__allowAdHocAttrs">`_allowAdHocAttrs`</a> is enabled by a class,
155      * non-attribute configuration properties don't get added as ad-hoc attributes.
156      *
157      * @property _NON_ATTRS_CFG
158      * @type Array
159      * @static
160      * @private
161      */
162     BaseCore._NON_ATTRS_CFG = ["plugins"];
164     /**
165      * This property controls whether or not instances of this class should
166      * allow users to add ad-hoc attributes through the constructor configuration
167      * hash.
168      *
169      * AdHoc attributes are attributes which are not defined by the class, and are
170      * not handled by the MyClass._NON_ATTRS_CFG
171      *
172      * @property _allowAdHocAttrs
173      * @type boolean
174      * @default undefined (false)
175      * @protected
176      */
178     /**
179      * The string to be used to identify instances of this class.
180      *
181      * Classes extending BaseCore, should define their own
182      * static NAME property, which should be camelCase by
183      * convention (e.g. MyClass.NAME = "myClass";).
184      *
185      * @property NAME
186      * @type String
187      * @static
188      */
189     BaseCore.NAME = "baseCore";
191     /**
192      * The default set of attributes which will be available for instances of this class, and
193      * their configuration. In addition to the configuration properties listed by
194      * AttributeCore's <a href="AttributeCore.html#method_addAttr">addAttr</a> method,
195      * the attribute can also be configured with a "cloneDefaultValue" property, which
196      * defines how the statically defined value field should be protected
197      * ("shallow", "deep" and false are supported values).
198      *
199      * By default if the value is an object literal or an array it will be "shallow"
200      * cloned, to protect the default value.
201      *
202      * @property ATTRS
203      * @type Object
204      * @static
205      */
206     BaseCore.ATTRS = {
207         /**
208          * Flag indicating whether or not this object
209          * has been through the init lifecycle phase.
210          *
211          * @attribute initialized
212          * @readonly
213          * @default false
214          * @type boolean
215          */
216         initialized: {
217             readOnly:true,
218             value:false
219         },
221         /**
222          * Flag indicating whether or not this object
223          * has been through the destroy lifecycle phase.
224          *
225          * @attribute destroyed
226          * @readonly
227          * @default false
228          * @type boolean
229          */
230         destroyed: {
231             readOnly:true,
232             value:false
233         }
234     };
236     /**
237     Provides a way to safely modify a `Y.BaseCore` subclass' static `ATTRS`
238     after the class has been defined or created.
240     BaseCore-based classes cache information about the class hierarchy in order
241     to efficiently create instances. This cache includes includes the aggregated
242     `ATTRS` configs. If the static `ATTRS` configs need to be modified after the
243     class has been defined or create, then use this method which will make sure
244     to clear any cached data before making any modifications.
246     @method modifyAttrs
247     @param {Function} [ctor] The constructor function whose `ATTRS` should be
248         modified. If a `ctor` function is not specified, then `this` is assumed
249         to be the constructor which hosts the `ATTRS`.
250     @param {Object} configs The collection of `ATTRS` configs to mix with the
251         existing attribute configurations.
252     @static
253     @since 3.10.0
254     **/
255     BaseCore.modifyAttrs = function (ctor, configs) {
256         // When called without a constructor, assume `this` is the constructor.
257         if (typeof ctor !== 'function') {
258             configs = ctor;
259             ctor    = this;
260         }
262         var attrs, attr, name;
264         // Eagerly create the `ATTRS` object if it doesn't already exist.
265         attrs = ctor.ATTRS || (ctor.ATTRS = {});
267         if (configs) {
268             // Clear cache because it has ATTRS aggregation data which is about
269             // to be modified.
270             ctor._CACHED_CLASS_DATA = null;
272             for (name in configs) {
273                 if (configs.hasOwnProperty(name)) {
274                     attr = attrs[name] || (attrs[name] = {});
275                     Y.mix(attr, configs[name], true);
276                 }
277             }
278         }
279     };
281     BaseCore.prototype = {
283         /**
284          * Internal construction logic for BaseCore.
285          *
286          * @method _initBase
287          * @param {Object} config The constructor configuration object
288          * @private
289          */
290         _initBase : function(config) {
291             Y.log('init called', 'life', 'base');
293             Y.stamp(this);
295             this._initAttribute(config);
297             // If Plugin.Host has been augmented [ through base-pluginhost ], setup it's
298             // initial state, but don't initialize Plugins yet. That's done after initialization.
299             var PluginHost = Y.Plugin && Y.Plugin.Host;
300             if (this._initPlugins && PluginHost) {
301                 PluginHost.call(this);
302             }
304             if (this._lazyAddAttrs !== false) { this._lazyAddAttrs = true; }
306             /**
307              * The string used to identify the class of this object.
308              *
309              * @deprecated Use this.constructor.NAME
310              * @property name
311              * @type String
312              */
313             this.name = this.constructor.NAME;
315             this.init.apply(this, arguments);
316         },
318         /**
319          * Initializes AttributeCore
320          *
321          * @method _initAttribute
322          * @private
323          */
324         _initAttribute: function() {
325             AttributeCore.call(this);
326         },
328         /**
329          * Init lifecycle method, invoked during construction. Sets up attributes
330          * and invokes initializers for the class hierarchy.
331          *
332          * @method init
333          * @chainable
334          * @param {Object} cfg Object with configuration property name/value pairs
335          * @return {BaseCore} A reference to this object
336          */
337         init: function(cfg) {
338             Y.log('init called', 'life', 'base');
340             this._baseInit(cfg);
342             return this;
343         },
345         /**
346          * Internal initialization implementation for BaseCore
347          *
348          * @method _baseInit
349          * @private
350          */
351         _baseInit: function(cfg) {
352             this._initHierarchy(cfg);
354             if (this._initPlugins) {
355                 // Need to initPlugins manually, to handle constructor parsing, static Plug parsing
356                 this._initPlugins(cfg);
357             }
358             this._set(INITIALIZED, true);
359         },
361         /**
362          * Destroy lifecycle method. Invokes destructors for the class hierarchy.
363          *
364          * @method destroy
365          * @return {BaseCore} A reference to this object
366          * @chainable
367          */
368         destroy: function() {
369             this._baseDestroy();
370             return this;
371         },
373         /**
374          * Internal destroy implementation for BaseCore
375          *
376          * @method _baseDestroy
377          * @private
378          */
379         _baseDestroy : function() {
380             if (this._destroyPlugins) {
381                 this._destroyPlugins();
382             }
383             this._destroyHierarchy();
384             this._set(DESTROYED, true);
385         },
387         /**
388          * Returns the class hierarchy for this object, with BaseCore being the last class in the array.
389          *
390          * @method _getClasses
391          * @protected
392          * @return {Function[]} An array of classes (constructor functions), making up the class hierarchy for this object.
393          * This value is cached the first time the method, or _getAttrCfgs, is invoked. Subsequent invocations return the
394          * cached value.
395          */
396         _getClasses : function() {
397             if (!this._classes) {
398                 this._initHierarchyData();
399             }
400             return this._classes;
401         },
403         /**
404          * Returns an aggregated set of attribute configurations, by traversing
405          * the class hierarchy.
406          *
407          * @method _getAttrCfgs
408          * @protected
409          * @return {Object} The hash of attribute configurations, aggregated across classes in the hierarchy
410          * This value is cached the first time the method, or _getClasses, is invoked. Subsequent invocations return
411          * the cached value.
412          */
413         _getAttrCfgs : function() {
414             if (!this._attrs) {
415                 this._initHierarchyData();
416             }
417             return this._attrs;
418         },
420         /**
421          * A helper method used to isolate the attrs config for this instance to pass to `addAttrs`,
422          * from the static cached ATTRS for the class.
423          *
424          * @method _getInstanceAttrCfgs
425          * @private
426          *
427          * @param {Object} allCfgs The set of all attribute configurations for this instance.
428          * Attributes will be removed from this set, if they belong to the filtered class, so
429          * that by the time all classes are processed, allCfgs will be empty.
430          *
431          * @return {Object} The set of attributes to be added for this instance, suitable
432          * for passing through to `addAttrs`.
433          */
434         _getInstanceAttrCfgs : function(allCfgs) {
436             var cfgs = {},
437                 cfg,
438                 val,
439                 subAttr,
440                 subAttrs,
441                 subAttrPath,
442                 attr,
443                 attrCfg,
444                 allSubAttrs = allCfgs._subAttrs,
445                 attrCfgProperties = this._attrCfgHash();
447             for (attr in allCfgs) {
449                 if (allCfgs.hasOwnProperty(attr) && attr !== "_subAttrs") {
451                     attrCfg = allCfgs[attr];
453                     // Need to isolate from allCfgs, because we're going to set values etc.
454                     cfg = cfgs[attr] = _wlmix({}, attrCfg, attrCfgProperties);
456                     val = cfg.value;
458                     if (val && (typeof val === "object")) {
459                         this._cloneDefaultValue(attr, cfg);
460                     }
462                     if (allSubAttrs && allSubAttrs.hasOwnProperty(attr)) {
463                         subAttrs = allCfgs._subAttrs[attr];
465                         for (subAttrPath in subAttrs) {
466                             subAttr = subAttrs[subAttrPath];
468                             if (subAttr.path) {
469                                 O.setValue(cfg.value, subAttr.path, subAttr.value);
470                             }
471                         }
472                     }
473                 }
474             }
476             return cfgs;
477         },
479         /**
480          * @method _filterAdHocAttrs
481          * @private
482          *
483          * @param {Object} allAttrs The set of all attribute configurations for this instance.
484          * Attributes will be removed from this set, if they belong to the filtered class, so
485          * that by the time all classes are processed, allCfgs will be empty.
486          * @param {Object} userVals The config object passed in by the user, from which adhoc attrs are to be filtered.
487          * @return {Object} The set of adhoc attributes passed in, in the form
488          * of an object with attribute name/configuration pairs.
489          */
490         _filterAdHocAttrs : function(allAttrs, userVals) {
491             var adHocs,
492                 nonAttrs = this._nonAttrs,
493                 attr;
495             if (userVals) {
496                 adHocs = {};
497                 for (attr in userVals) {
498                     if (!allAttrs[attr] && !nonAttrs[attr] && userVals.hasOwnProperty(attr)) {
499                         adHocs[attr] = {
500                             value:userVals[attr]
501                         };
502                     }
503                 }
504             }
506             return adHocs;
507         },
509         /**
510          * A helper method used by _getClasses and _getAttrCfgs, which determines both
511          * the array of classes and aggregate set of attribute configurations
512          * across the class hierarchy for the instance.
513          *
514          * @method _initHierarchyData
515          * @private
516          */
517         _initHierarchyData : function() {
519             var ctor = this.constructor,
520                 cachedClassData = ctor._CACHED_CLASS_DATA,
521                 c,
522                 i,
523                 l,
524                 attrCfg,
525                 attrCfgHash,
526                 needsAttrCfgHash = !ctor._ATTR_CFG_HASH,
527                 nonAttrsCfg,
528                 nonAttrs = {},
529                 classes = [],
530                 attrs = [];
532             // Start with `this` instance's constructor.
533             c = ctor;
535             if (!cachedClassData) {
537                 while (c) {
538                     // Add to classes
539                     classes[classes.length] = c;
541                     // Add to attributes
542                     if (c.ATTRS) {
543                         attrs[attrs.length] = c.ATTRS;
544                     }
546                     // Aggregate ATTR cfg whitelist.
547                     if (needsAttrCfgHash) {
548                         attrCfg     = c._ATTR_CFG;
549                         attrCfgHash = attrCfgHash || {};
551                         if (attrCfg) {
552                             for (i = 0, l = attrCfg.length; i < l; i += 1) {
553                                 attrCfgHash[attrCfg[i]] = true;
554                             }
555                         }
556                     }
558                     // Commenting out the if. We always aggregate, since we don't
559                     // know if we'll be needing this on the instance or not.
560                     // if (this._allowAdHocAttrs) {
561                         nonAttrsCfg = c._NON_ATTRS_CFG;
562                         if (nonAttrsCfg) {
563                             for (i = 0, l = nonAttrsCfg.length; i < l; i++) {
564                                 nonAttrs[nonAttrsCfg[i]] = true;
565                             }
566                         }
567                     //}
569                     c = c.superclass ? c.superclass.constructor : null;
570                 }
572                 // Cache computed `_ATTR_CFG_HASH` on the constructor.
573                 if (needsAttrCfgHash) {
574                     ctor._ATTR_CFG_HASH = attrCfgHash;
575                 }
577                 cachedClassData = ctor._CACHED_CLASS_DATA = {
578                     classes : classes,
579                     nonAttrs : nonAttrs,
580                     attrs : this._aggregateAttrs(attrs)
581                 };
583             }
585             this._classes = cachedClassData.classes;
586             this._attrs = cachedClassData.attrs;
587             this._nonAttrs = cachedClassData.nonAttrs;
588         },
590         /**
591          * Utility method to define the attribute hash used to filter/whitelist property mixes for
592          * this class for iteration performance reasons.
593          *
594          * @method _attrCfgHash
595          * @private
596          */
597         _attrCfgHash: function() {
598             return this.constructor._ATTR_CFG_HASH;
599         },
601         /**
602          * This method assumes that the value has already been checked to be an object.
603          * Since it's on a critical path, we don't want to re-do the check.
604          *
605          * @method _cloneDefaultValue
606          * @param {Object} cfg
607          * @private
608          */
609         _cloneDefaultValue : function(attr, cfg) {
611             var val = cfg.value,
612                 clone = cfg.cloneDefaultValue;
614             if (clone === DEEP || clone === true) {
615                 Y.log('Cloning default value for attribute:' + attr, 'info', 'base');
616                 cfg.value = Y.clone(val);
617             } else if (clone === SHALLOW) {
618                 Y.log('Merging default value for attribute:' + attr, 'info', 'base');
619                 cfg.value = Y.merge(val);
620             } else if ((clone === undefined && (OBJECT_CONSTRUCTOR === val.constructor || L.isArray(val)))) {
621                 cfg.value = Y.clone(val);
622             }
623             // else if (clone === false), don't clone the static default value.
624             // It's intended to be used by reference.
625         },
627         /**
628          * A helper method, used by _initHierarchyData to aggregate
629          * attribute configuration across the instances class hierarchy.
630          *
631          * The method will protect the attribute configuration value to protect the statically defined
632          * default value in ATTRS if required (if the value is an object literal, array or the
633          * attribute configuration has cloneDefaultValue set to shallow or deep).
634          *
635          * @method _aggregateAttrs
636          * @private
637          * @param {Array} allAttrs An array of ATTRS definitions across classes in the hierarchy
638          * (subclass first, Base last)
639          * @return {Object} The aggregate set of ATTRS definitions for the instance
640          */
641         _aggregateAttrs : function(allAttrs) {
643             var attr,
644                 attrs,
645                 subAttrsHash,
646                 cfg,
647                 path,
648                 i,
649                 cfgPropsHash = this._attrCfgHash(),
650                 aggAttr,
651                 aggAttrs = {};
653             if (allAttrs) {
654                 for (i = allAttrs.length-1; i >= 0; --i) {
656                     attrs = allAttrs[i];
658                     for (attr in attrs) {
659                         if (attrs.hasOwnProperty(attr)) {
661                             // PERF TODO: Do we need to merge here, since we're merging later in getInstanceAttrCfgs
662                             // Should we move this down to only merge if we hit the path or valueFn ifs below?
663                             cfg = _wlmix({}, attrs[attr], cfgPropsHash);
665                             path = null;
666                             if (attr.indexOf(DOT) !== -1) {
667                                 path = attr.split(DOT);
668                                 attr = path.shift();
669                             }
671                             aggAttr = aggAttrs[attr];
673                             if (path && aggAttr && aggAttr.value) {
675                                 subAttrsHash = aggAttrs._subAttrs;
677                                 if (!subAttrsHash) {
678                                     subAttrsHash = aggAttrs._subAttrs = {};
679                                 }
681                                 if (!subAttrsHash[attr]) {
682                                     subAttrsHash[attr] = {};
683                                 }
685                                 subAttrsHash[attr][path.join(DOT)] = {
686                                     value: cfg.value,
687                                     path : path
688                                 };
690                             } else if (!path) {
692                                 if (!aggAttr) {
693                                     aggAttrs[attr] = cfg;
694                                 } else {
695                                     if (aggAttr.valueFn && VALUE in cfg) {
696                                         aggAttr.valueFn = null;
697                                     }
699                                     // Mix into existing config.
700                                     _wlmix(aggAttr, cfg, cfgPropsHash);
701                                 }
702                             }
703                         }
704                     }
705                 }
706             }
708             return aggAttrs;
709         },
711         /**
712          * Initializes the class hierarchy for the instance, which includes
713          * initializing attributes for each class defined in the class's
714          * static <a href="#property_BaseCore.ATTRS">ATTRS</a> property and
715          * invoking the initializer method on the prototype of each class in the hierarchy.
716          *
717          * @method _initHierarchy
718          * @param {Object} userVals Object with configuration property name/value pairs
719          * @private
720          */
721         _initHierarchy : function(userVals) {
723             var lazy = this._lazyAddAttrs,
724                 constr,
725                 constrProto,
726                 i,
727                 l,
728                 ci,
729                 ei,
730                 el,
731                 ext,
732                 extProto,
733                 exts,
734                 instanceAttrs,
735                 initializers = [],
736                 classes = this._getClasses(),
737                 attrCfgs = this._getAttrCfgs(),
738                 cl = classes.length - 1;
740             // Constructors
741             for (ci = cl; ci >= 0; ci--) {
743                 constr = classes[ci];
744                 constrProto = constr.prototype;
745                 exts = constr._yuibuild && constr._yuibuild.exts;
747                 // Using INITIALIZER in hasOwnProperty check, for performance reasons (helps IE6 avoid GC thresholds when
748                 // referencing string literals). Not using it in apply, again, for performance "." is faster.
750                 if (constrProto.hasOwnProperty(INITIALIZER)) {
751                     // Store initializer while we're here and looping
752                     initializers[initializers.length] = constrProto.initializer;
753                 }
755                 if (exts) {
756                     for (ei = 0, el = exts.length; ei < el; ei++) {
758                         ext = exts[ei];
760                         // Ext Constructor
761                         ext.apply(this, arguments);
763                         extProto = ext.prototype;
764                         if (extProto.hasOwnProperty(INITIALIZER)) {
765                             // Store initializer while we're here and looping
766                             initializers[initializers.length] = extProto.initializer;
767                         }
768                     }
769                 }
770             }
772             // ATTRS
773             instanceAttrs = this._getInstanceAttrCfgs(attrCfgs);
775             if (this._preAddAttrs) {
776                 this._preAddAttrs(instanceAttrs, userVals, lazy);
777             }
779             if (this._allowAdHocAttrs) {
780                 this.addAttrs(this._filterAdHocAttrs(attrCfgs, userVals), userVals, lazy);
781             }
783             this.addAttrs(instanceAttrs, userVals, lazy);
785             // Initializers
786             for (i = 0, l = initializers.length; i < l; i++) {
787                 initializers[i].apply(this, arguments);
788             }
789         },
791         /**
792          * Destroys the class hierarchy for this instance by invoking
793          * the destructor method on the prototype of each class in the hierarchy.
794          *
795          * @method _destroyHierarchy
796          * @private
797          */
798         _destroyHierarchy : function() {
799             var constr,
800                 constrProto,
801                 ci, cl, ei, el, exts, extProto,
802                 classes = this._getClasses();
804             for (ci = 0, cl = classes.length; ci < cl; ci++) {
805                 constr = classes[ci];
806                 constrProto = constr.prototype;
807                 exts = constr._yuibuild && constr._yuibuild.exts;
809                 if (exts) {
810                     for (ei = 0, el = exts.length; ei < el; ei++) {
811                         extProto = exts[ei].prototype;
812                         if (extProto.hasOwnProperty(DESTRUCTOR)) {
813                             extProto.destructor.apply(this, arguments);
814                         }
815                     }
816                 }
818                 if (constrProto.hasOwnProperty(DESTRUCTOR)) {
819                     constrProto.destructor.apply(this, arguments);
820                 }
821             }
822         },
824         /**
825          * Default toString implementation. Provides the constructor NAME
826          * and the instance guid, if set.
827          *
828          * @method toString
829          * @return {String} String representation for this object
830          */
831         toString: function() {
832             return this.name + "[" + Y.stamp(this, true) + "]";
833         }
834     };
836     // Straightup augment, no wrapper functions
837     Y.mix(BaseCore, AttributeCore, false, null, 1);
839     // Fix constructor
840     BaseCore.prototype.constructor = BaseCore;
842     Y.BaseCore = BaseCore;
845 }, '3.13.0', {"requires": ["attribute-core"]});