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