]> git.wh0rd.org Git - tt-rss.git/blob - lib/dojo/_base/declare.js.uncompressed.js
upgrade dojo to 1.8.3 (refs #570)
[tt-rss.git] / lib / dojo / _base / declare.js.uncompressed.js
1 define("dojo/_base/declare", ["./kernel", "../has", "./lang"], function(dojo, has, lang){
2         // module:
3         //              dojo/_base/declare
4
5         var mix = lang.mixin, op = Object.prototype, opts = op.toString,
6                 xtor = new Function, counter = 0, cname = "constructor";
7
8         function err(msg, cls){ throw new Error("declare" + (cls ? " " + cls : "") + ": " + msg); }
9
10         // C3 Method Resolution Order (see http://www.python.org/download/releases/2.3/mro/)
11         function c3mro(bases, className){
12                 var result = [], roots = [{cls: 0, refs: []}], nameMap = {}, clsCount = 1,
13                         l = bases.length, i = 0, j, lin, base, top, proto, rec, name, refs;
14
15                 // build a list of bases naming them if needed
16                 for(; i < l; ++i){
17                         base = bases[i];
18                         if(!base){
19                                 err("mixin #" + i + " is unknown. Did you use dojo.require to pull it in?", className);
20                         }else if(opts.call(base) != "[object Function]"){
21                                 err("mixin #" + i + " is not a callable constructor.", className);
22                         }
23                         lin = base._meta ? base._meta.bases : [base];
24                         top = 0;
25                         // add bases to the name map
26                         for(j = lin.length - 1; j >= 0; --j){
27                                 proto = lin[j].prototype;
28                                 if(!proto.hasOwnProperty("declaredClass")){
29                                         proto.declaredClass = "uniqName_" + (counter++);
30                                 }
31                                 name = proto.declaredClass;
32                                 if(!nameMap.hasOwnProperty(name)){
33                                         nameMap[name] = {count: 0, refs: [], cls: lin[j]};
34                                         ++clsCount;
35                                 }
36                                 rec = nameMap[name];
37                                 if(top && top !== rec){
38                                         rec.refs.push(top);
39                                         ++top.count;
40                                 }
41                                 top = rec;
42                         }
43                         ++top.count;
44                         roots[0].refs.push(top);
45                 }
46
47                 // remove classes without external references recursively
48                 while(roots.length){
49                         top = roots.pop();
50                         result.push(top.cls);
51                         --clsCount;
52                         // optimization: follow a single-linked chain
53                         while(refs = top.refs, refs.length == 1){
54                                 top = refs[0];
55                                 if(!top || --top.count){
56                                         // branch or end of chain => do not end to roots
57                                         top = 0;
58                                         break;
59                                 }
60                                 result.push(top.cls);
61                                 --clsCount;
62                         }
63                         if(top){
64                                 // branch
65                                 for(i = 0, l = refs.length; i < l; ++i){
66                                         top = refs[i];
67                                         if(!--top.count){
68                                                 roots.push(top);
69                                         }
70                                 }
71                         }
72                 }
73                 if(clsCount){
74                         err("can't build consistent linearization", className);
75                 }
76
77                 // calculate the superclass offset
78                 base = bases[0];
79                 result[0] = base ?
80                         base._meta && base === result[result.length - base._meta.bases.length] ?
81                                 base._meta.bases.length : 1 : 0;
82
83                 return result;
84         }
85
86         function inherited(args, a, f){
87                 var name, chains, bases, caller, meta, base, proto, opf, pos,
88                         cache = this._inherited = this._inherited || {};
89
90                 // crack arguments
91                 if(typeof args == "string"){
92                         name = args;
93                         args = a;
94                         a = f;
95                 }
96                 f = 0;
97
98                 caller = args.callee;
99                 name = name || caller.nom;
100                 if(!name){
101                         err("can't deduce a name to call inherited()", this.declaredClass);
102                 }
103
104                 meta = this.constructor._meta;
105                 bases = meta.bases;
106
107                 pos = cache.p;
108                 if(name != cname){
109                         // method
110                         if(cache.c !== caller){
111                                 // cache bust
112                                 pos = 0;
113                                 base = bases[0];
114                                 meta = base._meta;
115                                 if(meta.hidden[name] !== caller){
116                                         // error detection
117                                         chains = meta.chains;
118                                         if(chains && typeof chains[name] == "string"){
119                                                 err("calling chained method with inherited: " + name, this.declaredClass);
120                                         }
121                                         // find caller
122                                         do{
123                                                 meta = base._meta;
124                                                 proto = base.prototype;
125                                                 if(meta && (proto[name] === caller && proto.hasOwnProperty(name) || meta.hidden[name] === caller)){
126                                                         break;
127                                                 }
128                                         }while(base = bases[++pos]); // intentional assignment
129                                         pos = base ? pos : -1;
130                                 }
131                         }
132                         // find next
133                         base = bases[++pos];
134                         if(base){
135                                 proto = base.prototype;
136                                 if(base._meta && proto.hasOwnProperty(name)){
137                                         f = proto[name];
138                                 }else{
139                                         opf = op[name];
140                                         do{
141                                                 proto = base.prototype;
142                                                 f = proto[name];
143                                                 if(f && (base._meta ? proto.hasOwnProperty(name) : f !== opf)){
144                                                         break;
145                                                 }
146                                         }while(base = bases[++pos]); // intentional assignment
147                                 }
148                         }
149                         f = base && f || op[name];
150                 }else{
151                         // constructor
152                         if(cache.c !== caller){
153                                 // cache bust
154                                 pos = 0;
155                                 meta = bases[0]._meta;
156                                 if(meta && meta.ctor !== caller){
157                                         // error detection
158                                         chains = meta.chains;
159                                         if(!chains || chains.constructor !== "manual"){
160                                                 err("calling chained constructor with inherited", this.declaredClass);
161                                         }
162                                         // find caller
163                                         while(base = bases[++pos]){ // intentional assignment
164                                                 meta = base._meta;
165                                                 if(meta && meta.ctor === caller){
166                                                         break;
167                                                 }
168                                         }
169                                         pos = base ? pos : -1;
170                                 }
171                         }
172                         // find next
173                         while(base = bases[++pos]){     // intentional assignment
174                                 meta = base._meta;
175                                 f = meta ? meta.ctor : base;
176                                 if(f){
177                                         break;
178                                 }
179                         }
180                         f = base && f;
181                 }
182
183                 // cache the found super method
184                 cache.c = f;
185                 cache.p = pos;
186
187                 // now we have the result
188                 if(f){
189                         return a === true ? f : f.apply(this, a || args);
190                 }
191                 // intentionally no return if a super method was not found
192         }
193
194         function getInherited(name, args){
195                 if(typeof name == "string"){
196                         return this.__inherited(name, args, true);
197                 }
198                 return this.__inherited(name, true);
199         }
200
201         function inherited__debug(args, a1, a2){
202                 var f = this.getInherited(args, a1);
203                 if(f){ return f.apply(this, a2 || a1 || args); }
204                 // intentionally no return if a super method was not found
205         }
206
207         var inheritedImpl = dojo.config.isDebug ? inherited__debug : inherited;
208
209         // emulation of "instanceof"
210         function isInstanceOf(cls){
211                 var bases = this.constructor._meta.bases;
212                 for(var i = 0, l = bases.length; i < l; ++i){
213                         if(bases[i] === cls){
214                                 return true;
215                         }
216                 }
217                 return this instanceof cls;
218         }
219
220         function mixOwn(target, source){
221                 // add props adding metadata for incoming functions skipping a constructor
222                 for(var name in source){
223                         if(name != cname && source.hasOwnProperty(name)){
224                                 target[name] = source[name];
225                         }
226                 }
227                 if(has("bug-for-in-skips-shadowed")){
228                         for(var extraNames= lang._extraNames, i= extraNames.length; i;){
229                                 name = extraNames[--i];
230                                 if(name != cname && source.hasOwnProperty(name)){
231                                           target[name] = source[name];
232                                 }
233                         }
234                 }
235         }
236
237         // implementation of safe mixin function
238         function safeMixin(target, source){
239                 // summary:
240                 //              Mix in properties skipping a constructor and decorating functions
241                 //              like it is done by declare().
242                 // target: Object
243                 //              Target object to accept new properties.
244                 // source: Object
245                 //              Source object for new properties.
246                 // description:
247                 //              This function is used to mix in properties like lang.mixin does,
248                 //              but it skips a constructor property and decorates functions like
249                 //              declare() does.
250                 //
251                 //              It is meant to be used with classes and objects produced with
252                 //              declare. Functions mixed in with dojo.safeMixin can use
253                 //              this.inherited() like normal methods.
254                 //
255                 //              This function is used to implement extend() method of a constructor
256                 //              produced with declare().
257                 //
258                 // example:
259                 //      |       var A = declare(null, {
260                 //      |               m1: function(){
261                 //      |                       console.log("A.m1");
262                 //      |               },
263                 //      |               m2: function(){
264                 //      |                       console.log("A.m2");
265                 //      |               }
266                 //      |       });
267                 //      |       var B = declare(A, {
268                 //      |               m1: function(){
269                 //      |                       this.inherited(arguments);
270                 //      |                       console.log("B.m1");
271                 //      |               }
272                 //      |       });
273                 //      |       B.extend({
274                 //      |               m2: function(){
275                 //      |                       this.inherited(arguments);
276                 //      |                       console.log("B.m2");
277                 //      |               }
278                 //      |       });
279                 //      |       var x = new B();
280                 //      |       dojo.safeMixin(x, {
281                 //      |               m1: function(){
282                 //      |                       this.inherited(arguments);
283                 //      |                       console.log("X.m1");
284                 //      |               },
285                 //      |               m2: function(){
286                 //      |                       this.inherited(arguments);
287                 //      |                       console.log("X.m2");
288                 //      |               }
289                 //      |       });
290                 //      |       x.m2();
291                 //      |       // prints:
292                 //      |       // A.m1
293                 //      |       // B.m1
294                 //      |       // X.m1
295
296                 var name, t;
297                 // add props adding metadata for incoming functions skipping a constructor
298                 for(name in source){
299                         t = source[name];
300                         if((t !== op[name] || !(name in op)) && name != cname){
301                                 if(opts.call(t) == "[object Function]"){
302                                         // non-trivial function method => attach its name
303                                         t.nom = name;
304                                 }
305                                 target[name] = t;
306                         }
307                 }
308                 if(has("bug-for-in-skips-shadowed")){
309                         for(var extraNames= lang._extraNames, i= extraNames.length; i;){
310                                 name = extraNames[--i];
311                                 t = source[name];
312                                 if((t !== op[name] || !(name in op)) && name != cname){
313                                         if(opts.call(t) == "[object Function]"){
314                                                 // non-trivial function method => attach its name
315                                                   t.nom = name;
316                                         }
317                                         target[name] = t;
318                                 }
319                         }
320                 }
321                 return target;
322         }
323
324         function extend(source){
325                 declare.safeMixin(this.prototype, source);
326                 return this;
327         }
328
329         function createSubclass(mixins){
330                 return declare([this].concat(mixins));
331         }
332
333         // chained constructor compatible with the legacy declare()
334         function chainedConstructor(bases, ctorSpecial){
335                 return function(){
336                         var a = arguments, args = a, a0 = a[0], f, i, m,
337                                 l = bases.length, preArgs;
338
339                         if(!(this instanceof a.callee)){
340                                 // not called via new, so force it
341                                 return applyNew(a);
342                         }
343
344                         //this._inherited = {};
345                         // perform the shaman's rituals of the original declare()
346                         // 1) call two types of the preamble
347                         if(ctorSpecial && (a0 && a0.preamble || this.preamble)){
348                                 // full blown ritual
349                                 preArgs = new Array(bases.length);
350                                 // prepare parameters
351                                 preArgs[0] = a;
352                                 for(i = 0;;){
353                                         // process the preamble of the 1st argument
354                                         a0 = a[0];
355                                         if(a0){
356                                                 f = a0.preamble;
357                                                 if(f){
358                                                         a = f.apply(this, a) || a;
359                                                 }
360                                         }
361                                         // process the preamble of this class
362                                         f = bases[i].prototype;
363                                         f = f.hasOwnProperty("preamble") && f.preamble;
364                                         if(f){
365                                                 a = f.apply(this, a) || a;
366                                         }
367                                         // one peculiarity of the preamble:
368                                         // it is called if it is not needed,
369                                         // e.g., there is no constructor to call
370                                         // let's watch for the last constructor
371                                         // (see ticket #9795)
372                                         if(++i == l){
373                                                 break;
374                                         }
375                                         preArgs[i] = a;
376                                 }
377                         }
378                         // 2) call all non-trivial constructors using prepared arguments
379                         for(i = l - 1; i >= 0; --i){
380                                 f = bases[i];
381                                 m = f._meta;
382                                 f = m ? m.ctor : f;
383                                 if(f){
384                                         f.apply(this, preArgs ? preArgs[i] : a);
385                                 }
386                         }
387                         // 3) continue the original ritual: call the postscript
388                         f = this.postscript;
389                         if(f){
390                                 f.apply(this, args);
391                         }
392                 };
393         }
394
395
396         // chained constructor compatible with the legacy declare()
397         function singleConstructor(ctor, ctorSpecial){
398                 return function(){
399                         var a = arguments, t = a, a0 = a[0], f;
400
401                         if(!(this instanceof a.callee)){
402                                 // not called via new, so force it
403                                 return applyNew(a);
404                         }
405
406                         //this._inherited = {};
407                         // perform the shaman's rituals of the original declare()
408                         // 1) call two types of the preamble
409                         if(ctorSpecial){
410                                 // full blown ritual
411                                 if(a0){
412                                         // process the preamble of the 1st argument
413                                         f = a0.preamble;
414                                         if(f){
415                                                 t = f.apply(this, t) || t;
416                                         }
417                                 }
418                                 f = this.preamble;
419                                 if(f){
420                                         // process the preamble of this class
421                                         f.apply(this, t);
422                                         // one peculiarity of the preamble:
423                                         // it is called even if it is not needed,
424                                         // e.g., there is no constructor to call
425                                         // let's watch for the last constructor
426                                         // (see ticket #9795)
427                                 }
428                         }
429                         // 2) call a constructor
430                         if(ctor){
431                                 ctor.apply(this, a);
432                         }
433                         // 3) continue the original ritual: call the postscript
434                         f = this.postscript;
435                         if(f){
436                                 f.apply(this, a);
437                         }
438                 };
439         }
440
441         // plain vanilla constructor (can use inherited() to call its base constructor)
442         function simpleConstructor(bases){
443                 return function(){
444                         var a = arguments, i = 0, f, m;
445
446                         if(!(this instanceof a.callee)){
447                                 // not called via new, so force it
448                                 return applyNew(a);
449                         }
450
451                         //this._inherited = {};
452                         // perform the shaman's rituals of the original declare()
453                         // 1) do not call the preamble
454                         // 2) call the top constructor (it can use this.inherited())
455                         for(; f = bases[i]; ++i){ // intentional assignment
456                                 m = f._meta;
457                                 f = m ? m.ctor : f;
458                                 if(f){
459                                         f.apply(this, a);
460                                         break;
461                                 }
462                         }
463                         // 3) call the postscript
464                         f = this.postscript;
465                         if(f){
466                                 f.apply(this, a);
467                         }
468                 };
469         }
470
471         function chain(name, bases, reversed){
472                 return function(){
473                         var b, m, f, i = 0, step = 1;
474                         if(reversed){
475                                 i = bases.length - 1;
476                                 step = -1;
477                         }
478                         for(; b = bases[i]; i += step){ // intentional assignment
479                                 m = b._meta;
480                                 f = (m ? m.hidden : b.prototype)[name];
481                                 if(f){
482                                         f.apply(this, arguments);
483                                 }
484                         }
485                 };
486         }
487
488         // forceNew(ctor)
489         // return a new object that inherits from ctor.prototype but
490         // without actually running ctor on the object.
491         function forceNew(ctor){
492                 // create object with correct prototype using a do-nothing
493                 // constructor
494                 xtor.prototype = ctor.prototype;
495                 var t = new xtor;
496                 xtor.prototype = null;  // clean up
497                 return t;
498         }
499
500         // applyNew(args)
501         // just like 'new ctor()' except that the constructor and its arguments come
502         // from args, which must be an array or an arguments object
503         function applyNew(args){
504                 // create an object with ctor's prototype but without
505                 // calling ctor on it.
506                 var ctor = args.callee, t = forceNew(ctor);
507                 // execute the real constructor on the new object
508                 ctor.apply(t, args);
509                 return t;
510         }
511
512         function declare(className, superclass, props){
513                 // summary:
514                 //              Create a feature-rich constructor from compact notation.
515                 // className: String?
516                 //              The optional name of the constructor (loosely, a "class")
517                 //              stored in the "declaredClass" property in the created prototype.
518                 //              It will be used as a global name for a created constructor.
519                 // superclass: Function|Function[]
520                 //              May be null, a Function, or an Array of Functions. This argument
521                 //              specifies a list of bases (the left-most one is the most deepest
522                 //              base).
523                 // props: Object
524                 //              An object whose properties are copied to the created prototype.
525                 //              Add an instance-initialization function by making it a property
526                 //              named "constructor".
527                 // returns: dojo/_base/declare.__DeclareCreatedObject
528                 //              New constructor function.
529                 // description:
530                 //              Create a constructor using a compact notation for inheritance and
531                 //              prototype extension.
532                 //
533                 //              Mixin ancestors provide a type of multiple inheritance.
534                 //              Prototypes of mixin ancestors are copied to the new class:
535                 //              changes to mixin prototypes will not affect classes to which
536                 //              they have been mixed in.
537                 //
538                 //              Ancestors can be compound classes created by this version of
539                 //              declare(). In complex cases all base classes are going to be
540                 //              linearized according to C3 MRO algorithm
541                 //              (see http://www.python.org/download/releases/2.3/mro/ for more
542                 //              details).
543                 //
544                 //              "className" is cached in "declaredClass" property of the new class,
545                 //              if it was supplied. The immediate super class will be cached in
546                 //              "superclass" property of the new class.
547                 //
548                 //              Methods in "props" will be copied and modified: "nom" property
549                 //              (the declared name of the method) will be added to all copied
550                 //              functions to help identify them for the internal machinery. Be
551                 //              very careful, while reusing methods: if you use the same
552                 //              function under different names, it can produce errors in some
553                 //              cases.
554                 //
555                 //              It is possible to use constructors created "manually" (without
556                 //              declare()) as bases. They will be called as usual during the
557                 //              creation of an instance, their methods will be chained, and even
558                 //              called by "this.inherited()".
559                 //
560                 //              Special property "-chains-" governs how to chain methods. It is
561                 //              a dictionary, which uses method names as keys, and hint strings
562                 //              as values. If a hint string is "after", this method will be
563                 //              called after methods of its base classes. If a hint string is
564                 //              "before", this method will be called before methods of its base
565                 //              classes.
566                 //
567                 //              If "constructor" is not mentioned in "-chains-" property, it will
568                 //              be chained using the legacy mode: using "after" chaining,
569                 //              calling preamble() method before each constructor, if available,
570                 //              and calling postscript() after all constructors were executed.
571                 //              If the hint is "after", it is chained as a regular method, but
572                 //              postscript() will be called after the chain of constructors.
573                 //              "constructor" cannot be chained "before", but it allows
574                 //              a special hint string: "manual", which means that constructors
575                 //              are not going to be chained in any way, and programmer will call
576                 //              them manually using this.inherited(). In the latter case
577                 //              postscript() will be called after the construction.
578                 //
579                 //              All chaining hints are "inherited" from base classes and
580                 //              potentially can be overridden. Be very careful when overriding
581                 //              hints! Make sure that all chained methods can work in a proposed
582                 //              manner of chaining.
583                 //
584                 //              Once a method was chained, it is impossible to unchain it. The
585                 //              only exception is "constructor". You don't need to define a
586                 //              method in order to supply a chaining hint.
587                 //
588                 //              If a method is chained, it cannot use this.inherited() because
589                 //              all other methods in the hierarchy will be called automatically.
590                 //
591                 //              Usually constructors and initializers of any kind are chained
592                 //              using "after" and destructors of any kind are chained as
593                 //              "before". Note that chaining assumes that chained methods do not
594                 //              return any value: any returned value will be discarded.
595                 //
596                 // example:
597                 //      |       declare("my.classes.bar", my.classes.foo, {
598                 //      |               // properties to be added to the class prototype
599                 //      |               someValue: 2,
600                 //      |               // initialization function
601                 //      |               constructor: function(){
602                 //      |                       this.myComplicatedObject = new ReallyComplicatedObject();
603                 //      |               },
604                 //      |               // other functions
605                 //      |               someMethod: function(){
606                 //      |                       doStuff();
607                 //      |               }
608                 //      |       });
609                 //
610                 // example:
611                 //      |       var MyBase = declare(null, {
612                 //      |               // constructor, properties, and methods go here
613                 //      |               // ...
614                 //      |       });
615                 //      |       var MyClass1 = declare(MyBase, {
616                 //      |               // constructor, properties, and methods go here
617                 //      |               // ...
618                 //      |       });
619                 //      |       var MyClass2 = declare(MyBase, {
620                 //      |               // constructor, properties, and methods go here
621                 //      |               // ...
622                 //      |       });
623                 //      |       var MyDiamond = declare([MyClass1, MyClass2], {
624                 //      |               // constructor, properties, and methods go here
625                 //      |               // ...
626                 //      |       });
627                 //
628                 // example:
629                 //      |       var F = function(){ console.log("raw constructor"); };
630                 //      |       F.prototype.method = function(){
631                 //      |               console.log("raw method");
632                 //      |       };
633                 //      |       var A = declare(F, {
634                 //      |               constructor: function(){
635                 //      |                       console.log("A.constructor");
636                 //      |               },
637                 //      |               method: function(){
638                 //      |                       console.log("before calling F.method...");
639                 //      |                       this.inherited(arguments);
640                 //      |                       console.log("...back in A");
641                 //      |               }
642                 //      |       });
643                 //      |       new A().method();
644                 //      |       // will print:
645                 //      |       // raw constructor
646                 //      |       // A.constructor
647                 //      |       // before calling F.method...
648                 //      |       // raw method
649                 //      |       // ...back in A
650                 //
651                 // example:
652                 //      |       var A = declare(null, {
653                 //      |               "-chains-": {
654                 //      |                       destroy: "before"
655                 //      |               }
656                 //      |       });
657                 //      |       var B = declare(A, {
658                 //      |               constructor: function(){
659                 //      |                       console.log("B.constructor");
660                 //      |               },
661                 //      |               destroy: function(){
662                 //      |                       console.log("B.destroy");
663                 //      |               }
664                 //      |       });
665                 //      |       var C = declare(B, {
666                 //      |               constructor: function(){
667                 //      |                       console.log("C.constructor");
668                 //      |               },
669                 //      |               destroy: function(){
670                 //      |                       console.log("C.destroy");
671                 //      |               }
672                 //      |       });
673                 //      |       new C().destroy();
674                 //      |       // prints:
675                 //      |       // B.constructor
676                 //      |       // C.constructor
677                 //      |       // C.destroy
678                 //      |       // B.destroy
679                 //
680                 // example:
681                 //      |       var A = declare(null, {
682                 //      |               "-chains-": {
683                 //      |                       constructor: "manual"
684                 //      |               }
685                 //      |       });
686                 //      |       var B = declare(A, {
687                 //      |               constructor: function(){
688                 //      |                       // ...
689                 //      |                       // call the base constructor with new parameters
690                 //      |                       this.inherited(arguments, [1, 2, 3]);
691                 //      |                       // ...
692                 //      |               }
693                 //      |       });
694                 //
695                 // example:
696                 //      |       var A = declare(null, {
697                 //      |               "-chains-": {
698                 //      |                       m1: "before"
699                 //      |               },
700                 //      |               m1: function(){
701                 //      |                       console.log("A.m1");
702                 //      |               },
703                 //      |               m2: function(){
704                 //      |                       console.log("A.m2");
705                 //      |               }
706                 //      |       });
707                 //      |       var B = declare(A, {
708                 //      |               "-chains-": {
709                 //      |                       m2: "after"
710                 //      |               },
711                 //      |               m1: function(){
712                 //      |                       console.log("B.m1");
713                 //      |               },
714                 //      |               m2: function(){
715                 //      |                       console.log("B.m2");
716                 //      |               }
717                 //      |       });
718                 //      |       var x = new B();
719                 //      |       x.m1();
720                 //      |       // prints:
721                 //      |       // B.m1
722                 //      |       // A.m1
723                 //      |       x.m2();
724                 //      |       // prints:
725                 //      |       // A.m2
726                 //      |       // B.m2
727
728                 // crack parameters
729                 if(typeof className != "string"){
730                         props = superclass;
731                         superclass = className;
732                         className = "";
733                 }
734                 props = props || {};
735
736                 var proto, i, t, ctor, name, bases, chains, mixins = 1, parents = superclass;
737
738                 // build a prototype
739                 if(opts.call(superclass) == "[object Array]"){
740                         // C3 MRO
741                         bases = c3mro(superclass, className);
742                         t = bases[0];
743                         mixins = bases.length - t;
744                         superclass = bases[mixins];
745                 }else{
746                         bases = [0];
747                         if(superclass){
748                                 if(opts.call(superclass) == "[object Function]"){
749                                         t = superclass._meta;
750                                         bases = bases.concat(t ? t.bases : superclass);
751                                 }else{
752                                         err("base class is not a callable constructor.", className);
753                                 }
754                         }else if(superclass !== null){
755                                 err("unknown base class. Did you use dojo.require to pull it in?", className);
756                         }
757                 }
758                 if(superclass){
759                         for(i = mixins - 1;; --i){
760                                 proto = forceNew(superclass);
761                                 if(!i){
762                                         // stop if nothing to add (the last base)
763                                         break;
764                                 }
765                                 // mix in properties
766                                 t = bases[i];
767                                 (t._meta ? mixOwn : mix)(proto, t.prototype);
768                                 // chain in new constructor
769                                 ctor = new Function;
770                                 ctor.superclass = superclass;
771                                 ctor.prototype = proto;
772                                 superclass = proto.constructor = ctor;
773                         }
774                 }else{
775                         proto = {};
776                 }
777                 // add all properties
778                 declare.safeMixin(proto, props);
779                 // add constructor
780                 t = props.constructor;
781                 if(t !== op.constructor){
782                         t.nom = cname;
783                         proto.constructor = t;
784                 }
785
786                 // collect chains and flags
787                 for(i = mixins - 1; i; --i){ // intentional assignment
788                         t = bases[i]._meta;
789                         if(t && t.chains){
790                                 chains = mix(chains || {}, t.chains);
791                         }
792                 }
793                 if(proto["-chains-"]){
794                         chains = mix(chains || {}, proto["-chains-"]);
795                 }
796
797                 // build ctor
798                 t = !chains || !chains.hasOwnProperty(cname);
799                 bases[0] = ctor = (chains && chains.constructor === "manual") ? simpleConstructor(bases) :
800                         (bases.length == 1 ? singleConstructor(props.constructor, t) : chainedConstructor(bases, t));
801
802                 // add meta information to the constructor
803                 ctor._meta  = {bases: bases, hidden: props, chains: chains,
804                         parents: parents, ctor: props.constructor};
805                 ctor.superclass = superclass && superclass.prototype;
806                 ctor.extend = extend;
807                 ctor.createSubclass = createSubclass;
808                 ctor.prototype = proto;
809                 proto.constructor = ctor;
810
811                 // add "standard" methods to the prototype
812                 proto.getInherited = getInherited;
813                 proto.isInstanceOf = isInstanceOf;
814                 proto.inherited    = inheritedImpl;
815                 proto.__inherited  = inherited;
816
817                 // add name if specified
818                 if(className){
819                         proto.declaredClass = className;
820                         lang.setObject(className, ctor);
821                 }
822
823                 // build chains and add them to the prototype
824                 if(chains){
825                         for(name in chains){
826                                 if(proto[name] && typeof chains[name] == "string" && name != cname){
827                                         t = proto[name] = chain(name, bases, chains[name] === "after");
828                                         t.nom = name;
829                                 }
830                         }
831                 }
832                 // chained methods do not return values
833                 // no need to chain "invisible" functions
834
835                 return ctor;    // Function
836         }
837
838         /*=====
839         declare.__DeclareCreatedObject = {
840                 // summary:
841                 //              dojo/_base/declare() returns a constructor `C`.   `new C()` returns an Object with the following
842                 //              methods, in addition to the methods and properties specified via the arguments passed to declare().
843
844                 inherited: function(name, args, newArgs){
845                         // summary:
846                         //              Calls a super method.
847                         // name: String?
848                         //              The optional method name. Should be the same as the caller's
849                         //              name. Usually "name" is specified in complex dynamic cases, when
850                         //              the calling method was dynamically added, undecorated by
851                         //              declare(), and it cannot be determined.
852                         // args: Arguments
853                         //              The caller supply this argument, which should be the original
854                         //              "arguments".
855                         // newArgs: Object?
856                         //              If "true", the found function will be returned without
857                         //              executing it.
858                         //              If Array, it will be used to call a super method. Otherwise
859                         //              "args" will be used.
860                         // returns:
861                         //              Whatever is returned by a super method, or a super method itself,
862                         //              if "true" was specified as newArgs.
863                         // description:
864                         //              This method is used inside method of classes produced with
865                         //              declare() to call a super method (next in the chain). It is
866                         //              used for manually controlled chaining. Consider using the regular
867                         //              chaining, because it is faster. Use "this.inherited()" only in
868                         //              complex cases.
869                         //
870                         //              This method cannot me called from automatically chained
871                         //              constructors including the case of a special (legacy)
872                         //              constructor chaining. It cannot be called from chained methods.
873                         //
874                         //              If "this.inherited()" cannot find the next-in-chain method, it
875                         //              does nothing and returns "undefined". The last method in chain
876                         //              can be a default method implemented in Object, which will be
877                         //              called last.
878                         //
879                         //              If "name" is specified, it is assumed that the method that
880                         //              received "args" is the parent method for this call. It is looked
881                         //              up in the chain list and if it is found the next-in-chain method
882                         //              is called. If it is not found, the first-in-chain method is
883                         //              called.
884                         //
885                         //              If "name" is not specified, it will be derived from the calling
886                         //              method (using a methoid property "nom").
887                         //
888                         // example:
889                         //      |       var B = declare(A, {
890                         //      |               method1: function(a, b, c){
891                         //      |                       this.inherited(arguments);
892                         //      |               },
893                         //      |               method2: function(a, b){
894                         //      |                       return this.inherited(arguments, [a + b]);
895                         //      |               }
896                         //      |       });
897                         //      |       // next method is not in the chain list because it is added
898                         //      |       // manually after the class was created.
899                         //      |       B.prototype.method3 = function(){
900                         //      |               console.log("This is a dynamically-added method.");
901                         //      |               this.inherited("method3", arguments);
902                         //      |       };
903                         // example:
904                         //      |       var B = declare(A, {
905                         //      |               method: function(a, b){
906                         //      |                       var super = this.inherited(arguments, true);
907                         //      |                       // ...
908                         //      |                       if(!super){
909                         //      |                               console.log("there is no super method");
910                         //      |                               return 0;
911                         //      |                       }
912                         //      |                       return super.apply(this, arguments);
913                         //      |               }
914                         //      |       });
915                         return  {};     // Object
916                 },
917
918                 getInherited: function(name, args){
919                         // summary:
920                         //              Returns a super method.
921                         // name: String?
922                         //              The optional method name. Should be the same as the caller's
923                         //              name. Usually "name" is specified in complex dynamic cases, when
924                         //              the calling method was dynamically added, undecorated by
925                         //              declare(), and it cannot be determined.
926                         // args: Arguments
927                         //              The caller supply this argument, which should be the original
928                         //              "arguments".
929                         // returns:
930                         //              Returns a super method (Function) or "undefined".
931                         // description:
932                         //              This method is a convenience method for "this.inherited()".
933                         //              It uses the same algorithm but instead of executing a super
934                         //              method, it returns it, or "undefined" if not found.
935                         //
936                         // example:
937                         //      |       var B = declare(A, {
938                         //      |               method: function(a, b){
939                         //      |                       var super = this.getInherited(arguments);
940                         //      |                       // ...
941                         //      |                       if(!super){
942                         //      |                               console.log("there is no super method");
943                         //      |                               return 0;
944                         //      |                       }
945                         //      |                       return super.apply(this, arguments);
946                         //      |               }
947                         //      |       });
948                         return  {};     // Object
949                 },
950
951                 isInstanceOf: function(cls){
952                         // summary:
953                         //              Checks the inheritance chain to see if it is inherited from this
954                         //              class.
955                         // cls: Function
956                         //              Class constructor.
957                         // returns:
958                         //              "true", if this object is inherited from this class, "false"
959                         //              otherwise.
960                         // description:
961                         //              This method is used with instances of classes produced with
962                         //              declare() to determine of they support a certain interface or
963                         //              not. It models "instanceof" operator.
964                         //
965                         // example:
966                         //      |       var A = declare(null, {
967                         //      |               // constructor, properties, and methods go here
968                         //      |               // ...
969                         //      |       });
970                         //      |       var B = declare(null, {
971                         //      |               // constructor, properties, and methods go here
972                         //      |               // ...
973                         //      |       });
974                         //      |       var C = declare([A, B], {
975                         //      |               // constructor, properties, and methods go here
976                         //      |               // ...
977                         //      |       });
978                         //      |       var D = declare(A, {
979                         //      |               // constructor, properties, and methods go here
980                         //      |               // ...
981                         //      |       });
982                         //      |
983                         //      |       var a = new A(), b = new B(), c = new C(), d = new D();
984                         //      |
985                         //      |       console.log(a.isInstanceOf(A)); // true
986                         //      |       console.log(b.isInstanceOf(A)); // false
987                         //      |       console.log(c.isInstanceOf(A)); // true
988                         //      |       console.log(d.isInstanceOf(A)); // true
989                         //      |
990                         //      |       console.log(a.isInstanceOf(B)); // false
991                         //      |       console.log(b.isInstanceOf(B)); // true
992                         //      |       console.log(c.isInstanceOf(B)); // true
993                         //      |       console.log(d.isInstanceOf(B)); // false
994                         //      |
995                         //      |       console.log(a.isInstanceOf(C)); // false
996                         //      |       console.log(b.isInstanceOf(C)); // false
997                         //      |       console.log(c.isInstanceOf(C)); // true
998                         //      |       console.log(d.isInstanceOf(C)); // false
999                         //      |
1000                         //      |       console.log(a.isInstanceOf(D)); // false
1001                         //      |       console.log(b.isInstanceOf(D)); // false
1002                         //      |       console.log(c.isInstanceOf(D)); // false
1003                         //      |       console.log(d.isInstanceOf(D)); // true
1004                         return  {};     // Object
1005                 },
1006
1007                 extend: function(source){
1008                         // summary:
1009                         //              Adds all properties and methods of source to constructor's
1010                         //              prototype, making them available to all instances created with
1011                         //              constructor. This method is specific to constructors created with
1012                         //              declare().
1013                         // source: Object
1014                         //              Source object which properties are going to be copied to the
1015                         //              constructor's prototype.
1016                         // description:
1017                         //              Adds source properties to the constructor's prototype. It can
1018                         //              override existing properties.
1019                         //
1020                         //              This method is similar to dojo.extend function, but it is specific
1021                         //              to constructors produced by declare(). It is implemented
1022                         //              using dojo.safeMixin, and it skips a constructor property,
1023                         //              and properly decorates copied functions.
1024                         //
1025                         // example:
1026                         //      |       var A = declare(null, {
1027                         //      |               m1: function(){},
1028                         //      |               s1: "Popokatepetl"
1029                         //      |       });
1030                         //      |       A.extend({
1031                         //      |               m1: function(){},
1032                         //      |               m2: function(){},
1033                         //      |               f1: true,
1034                         //      |               d1: 42
1035                         //      |       });
1036                 }
1037         };
1038         =====*/
1039
1040         // For back-compat, remove for 2.0
1041         dojo.safeMixin = declare.safeMixin = safeMixin;
1042         dojo.declare = declare;
1043
1044         return declare;
1045 });