Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

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