2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 // Test case for ActionScript inheritance
22 // compile this test case with Ming makeswf, and then
23 // execute it like this gnash -1 -r 0 -v out.swf
25 rcsid
="$Id: Inheritance.as,v 1.64 2008/06/19 10:51:44 strk Exp $";
28 check_equals
(typeof(Object.prototype
.constructor
), 'function');
29 check_equals
(Object.prototype
.constructor
, Object);
31 // Function.apply is Function.__proto__.apply
32 #if OUTPUT_VERSION
> 5
33 check
(typeof(Function.apply
) != undefined);
35 check
(Function.apply
== Function.__proto__
.apply
);
37 // Confirm '__proto__' and 'prototype' members
38 // for Function to be the same thing
39 Function.prototype
.fake
= function(){};
40 check
(Function.fake
== Function.__proto__
.fake
);
41 check
(Function.fake
== Function.prototype
.fake
);
43 // Make 'functionObject' be an instance of Function (an object)
44 var functionObject
= new Function();
46 #if OUTPUT_VERSION
> 5
47 check_equals
(typeof(functionObject
), 'object');
48 check
(functionObject
.hasOwnProperty
('__constructor__'));
49 check_equals
(functionObject
.__constructor__
, Function);
51 // This is because SWF5 does not support Function class.
52 check_equals
(typeof(functionObject
), 'undefined');
55 // functionObject '__proto__' is a reference to
56 // it's constructor's 'prototype' member.
57 check_equals
(functionObject
.__proto__
, Function.prototype
);
58 check_equals
(functionObject
.__proto__
.constructor
, Function);
60 // functionObject.apply should be functionObject.__proto__.apply
61 #if OUTPUT_VERSION
> 5
62 check
(functionObject
.apply
!= undefined);
63 check
(functionObject
.apply
== Function.prototype
.apply
);
64 check
(functionObject
.apply
== functionObject
.__proto__
.apply
);
67 // functionObject is an Object, not functionObject Function,
68 // so it doesn't have functionObject 'prototype' member
70 check
(functionObject
.prototype
== undefined);
72 #if OUTPUT_VERSION
> 5
73 functionObject
.prototype
= {a
:1};
74 check_equals
(functionObject
.prototype
.a
, 1);
77 // Make 'userFunc' be a function (should inherit Function things)
78 var userFunc
= function() {};
79 #if OUTPUT_VERSION
> 5
80 check_equals
(userFunc
.__proto__
, Function.prototype
);
82 check_equals
(userFunc
.prototype
.constructor
, userFunc
);
83 check_equals
(userFunc
.prototype
.apply
, undefined);
84 check_equals
(userFunc
.apply
, Function.prototype
.apply
);
86 // Override the inherited apply() method
87 #if OUTPUT_VERSION
> 5
88 // Function.apply was introduced in SWF6
89 userFunc
.apply
= function() {};
90 check
(userFunc
.apply
!= Function.prototype
.apply
);
94 // Define the Ball constructor
95 function Ball
(radius
) {
98 check
(Ball
.prototype
.constructor
== Ball
);
99 Ball
.prototype
.gravity
= 9.8;
101 var myBall
= new Ball
(3);
102 #if OUTPUT_VERSION
> 5
103 check
(myBall
.hasOwnProperty
('__constructor__'));
104 check_equals
(myBall
.__constructor__
, Ball
);
106 check
(myBall
.gravity
== 9.8);
107 check
(myBall
.radius
== 3);
109 function sayHello
() { return "Hello"; }
110 Ball
.prototype
.sayHello
= sayHello
;
111 check
(myBall
.sayHello
() == "Hello");
112 check
(myBall
.gravity
== 9.8);
114 check
(myBall
.gravity
== 5);
115 check
(myBall
.__proto__
== Ball
.prototype
);
117 check
(!_root
.hasOwnProperty
('__constructor__'));
119 //-------------------------------------------------------------------------
120 // Try changing value of __constructor__ from within the constructor itself
121 //-------------------------------------------------------------------------
123 function TypeChanger
(changeit
)
125 if ( changeit
) this.__constructor__
= Object;
127 #if OUTPUT_VERSION
> 5
128 check_equals
(TypeChanger
.__proto__
, Function.prototype
);
131 check
(! TypeChanger
.prototype
instanceof TypeChanger
);
133 o1
= new TypeChanger
(false);
134 check_equals
(o1
.__proto__
, TypeChanger
.prototype
);
135 check_equals
(o1
.__constructor__
, TypeChanger
);
136 check
(o1
instanceof TypeChanger
);
137 check
(o1
instanceof Object);
138 o2
= new TypeChanger
(true);
139 check_equals
(o2
.__constructor__
, Object);
140 check
(o2
instanceof TypeChanger
);
141 check
(o2
instanceof Object);
143 //-------------------------------------------------------------------------
144 // Old-style inheritance
145 //-------------------------------------------------------------------------
147 // Define a superclass
148 function SuperClass
() {
149 this.sayHello
= function() { return "hello from SuperClass"; };
152 // Define a class derived from SuperClass
153 function SubClass
() {}
154 check_equals
(SubClass
.prototype
.constructor
, SubClass
);
155 check_equals
(typeof(SubClass
.prototype
.__constructor__
), 'undefined');
157 SubClass
.prototype
= new SuperClass
();
158 check_equals
(SubClass
.prototype
.constructor
, SuperClass
);
160 subInstance
= new SubClass
();
161 #if OUTPUT_VERSION
> 5
162 check
(subInstance
.hasOwnProperty
('__constructor__'));
163 check_equals
(subInstance
.__constructor__
, SubClass
);
164 check_equals
(subInstance
.__proto__
.constructor
, SuperClass
);
167 check_equals
(subInstance
.sayHello
(), "hello from SuperClass" );
168 SubClass
.prototype
.sayHello
= function() { return "hello from SubClass"; };
169 check_equals
(subInstance
.sayHello
(), "hello from SubClass" );
170 subInstance
.sayHello
= function() { return "hello from subInstance"; };
171 check_equals
(subInstance
.sayHello
(), "hello from subInstance" );
173 // Test the instanceOf operator
174 check
(subInstance instanceOf SubClass
);
175 check
(subInstance instanceOf SuperClass
);
176 check
(subInstance instanceOf
Object);
179 //------------------------------------------------
180 // Test the 'super' keyword
181 //------------------------------------------------
183 #if OUTPUT_VERSION
> 5
184 function BaseClass
() {}
185 BaseClass
.prototype
.sayHello
= function () {
186 return "Hello from BaseClass";
188 function DerivedClass
() {}
189 DerivedClass
.prototype
= new BaseClass
();
190 check_equals
(typeof(DerivedClass
.prototype
.__constructor__
), 'function');
191 check
(DerivedClass
.prototype
.hasOwnProperty
('__constructor__'));
192 check_equals
(DerivedClass
.prototype
.__constructor__
, BaseClass
);
193 check
(DerivedClass
.prototype
.__constructor__
!= DerivedClass
);
194 DerivedClass
.prototype
.sayHello
= function () {
195 return "Hello from DerivedClass";
197 DerivedClass
.prototype
.saySuperHello
= function () {
198 return super.sayHello
();
200 var derived
= new DerivedClass
();
201 var greeting
= derived
.saySuperHello
();
202 check_equals
(greeting
, "Hello from BaseClass");
204 DerivedClass
.prototype
.typeofSuper
= function() { return typeof(super); };
205 check_equals
(derived
.typeofSuper
(), 'object');
206 check_equals
(DerivedClass
.prototype
.typeofSuper
(), 'object');
208 DerivedClass
.prototype
.getSuper
= function() { return super; };
209 s
= derived
.getSuper
();
210 check_equals
(typeof(s
), 'object');
211 check_equals
(s
.sayHello
, BaseClass
.prototype
.sayHello
);
212 check
(!s
.hasOwnProperty
('sayHello')); // sayHello is not copied to 's'
213 check_equals
(s
.__proto__
, Object.prototype
); // nor it's found in __proto__
214 check_equals
(typeof(s
.prototype
), 'undefined');
215 check_equals
(typeof(s
.constructor
), 'function');
216 check_equals
(s
.constructor
, BaseClass
); // maybe sayHello is looked for here...
217 check_equals
(typeof(s
.__constructor__
), 'undefined');
218 check
(s
!= BaseClass
.prototype
);
220 DerivedClass
.prototype
.typeofThis
= function() { return typeof(this); };
221 check_equals
(derived
.typeofThis
(), 'object');
222 check_equals
(DerivedClass
.prototype
.typeofThis
(), 'object');
224 DerivedClass
.prototype
.getThis
= function() { return this; };
225 check_equals
(derived
.getThis
(), derived
);
226 check_equals
(DerivedClass
.prototype
.getThis
(), DerivedClass
.prototype
);
228 #endif
// OUTPUT_VERSION > 5
229 check_equals
(super, undefined);
232 function A
() { ActorCalls
++; }
233 A
.prototype
.whoami
= function() {
236 function B
() { BctorCalls
++; }
239 check_equals
(bo
.whoami
(), "A");
240 B
.prototype
.whoami
= function() {
241 return super.whoami
()+"."+"B";
243 #if OUTPUT_VERSION
< 6
244 check_equals
(bo
.whoami
(), ".B");
246 check_equals
(bo
.whoami
(), "A.B");
251 #if OUTPUT_VERSION
> 6
252 check_equals
(co
.whoami
(), "A.B");
254 # if OUTPUT_VERSION
== 6
255 check_equals
(co
.whoami
(), "A.B.B");
257 check_equals
(co
.whoami
(), ".B");
260 C
.prototype
.whoami
= function() {
261 return super.whoami
()+"."+"C";
263 #if OUTPUT_VERSION
> 5
264 check_equals
(co
.whoami
(), "A.B.C");
266 check_equals
(co
.whoami
(), ".C");
269 // Test gaps in inheritance chain
270 function F
() { FctorCalls
++; /*note("F ctor");*/ }
271 F
.prototype
.myName
= function() { return "F"; };
272 A
.prototype
.__constructor__
= F
; A
.prototype
.__proto__
= F
.prototype
;
273 A
.prototype
.myName
= function() { /*note("A.prototype.myName called");*/ super(); return super.myName
()+"A"; };
274 C
.prototype
.myName
= function() { /*note("C.prototype.myName called");*/ super(); return super.myName
()+"C"; };
279 #if OUTPUT_VERSION
< 6
280 check_equals
(n
, "C"); // no super
281 check_equals
(FctorCalls
, 0); // no super
282 check_equals
(BctorCalls
, 0); // no super
283 check_equals
(ActorCalls
, 0); // no super
285 #if OUTPUT_VERSION
== 6
286 check_equals
(n
, "FAAC"); // super in C references B proto and B ctor no matter where myName was found
287 check_equals
(FctorCalls
, 1);
288 check_equals
(BctorCalls
, 1);
289 check_equals
(ActorCalls
, 1);
291 #if OUTPUT_VERSION
> 6
292 check_equals
(n
, "FAC"); // super in C references A proto and B ctor
293 check_equals
(FctorCalls
, 1);
294 check_equals
(BctorCalls
, 1);
295 check_equals
(ActorCalls
, 0); // B.prototype calling super() calls F prototype, not A's
299 delete A
.prototype
.myName
;
304 #if OUTPUT_VERSION
< 6
305 check_equals
(n
, "C"); // no super
306 check_equals
(FctorCalls
, 0); // no super
307 check_equals
(BctorCalls
, 0); // no super
308 check_equals
(ActorCalls
, 0); // no super
310 check_equals
(co
.myName
(), "FC"); // super in C references F proto and B ctor
311 check_equals
(FctorCalls
, 0);
312 check_equals
(BctorCalls
, 2);
313 check_equals
(ActorCalls
, 0);
316 // Now test 'super' at the top of the inheritance chain
317 F
.prototype
.myName
= function() { /*note("F.prototype.myName called");*/ super(); return super.myName
()+"F"; };
321 //note("Calling co (instanceof C) myName method");
323 //note("Done calling co (instanceof C) myName method");
324 #if OUTPUT_VERSION
< 6
325 check_equals
(n
, "C"); // no super
326 check_equals
(FctorCalls
, 0); // no super
327 check_equals
(BctorCalls
, 0); // no super
328 check_equals
(ActorCalls
, 0); // no super
330 #if OUTPUT_VERSION
== 6
331 check_equals
(n
, "FFFC"); // super in C references F proto
332 check_equals
(FctorCalls
, 1);
333 check_equals
(BctorCalls
, 1);
334 check_equals
(ActorCalls
, 1);
336 #if OUTPUT_VERSION
> 6
337 check_equals
(n
, "undefinedFFC");
338 check_equals
(FctorCalls
, 1);
339 check_equals
(BctorCalls
, 1);
340 check_equals
(ActorCalls
, 0);
343 //------------------------------------------------
345 //------------------------------------------------
348 /// THese have been moved here from inheritance.as
349 var obj
= new Object({a
:1});
351 check_equals
(obj
.__proto__
.constructor
, Object);
352 check
(obj instanceOf
Object);
354 function SubObj1
() {}
355 var sobj1
= new SubObj1
();
357 check_equals
(sobj1
.__proto__
.constructor
, SubObj1
);
358 #if OUTPUT_VERSION
> 5
359 check
(SubObj1 instanceOf
Function);
360 check
(Function instanceOf
Object);
361 check
(SubObj1 instanceOf
Object);
364 // inheritance chain is NOT subobj1,SubObj1,Function,Object, as the
365 // above might suggest...
366 check
(!sobj1 instanceOf
Function);
368 // but still, sobj1 is an instance of Object *and* SubObj1
369 check
(sobj1 instanceOf
Object);
370 check
(sobj1 instanceOf SubObj1
);
372 check
(SubObj1
.prototype
!= undefined);
373 check_equals
(SubObj1
.prototype
.constructor
, SubObj1
);
375 #if OUTPUT_VERSION
> 5
376 check_equals
(SubObj1
.prototype
.constructor
.__proto__
.constructor
, Function);
379 //------------------------------------------------
380 // Test the 'extends' tag (require ming > 0.4.0.beta3)
381 //------------------------------------------------
384 #ifdef MING_SUPPORTS_ASM_EXTENDS
386 function BaseClass1
() { this.baseClassCtorCalled
= 1; }
387 BaseClass1
.prototype
.var1
= "var_in_Base_prototype";
388 function DerivedClass1
() { this.derivedClassCtorCalled
= 1; }
389 DerivedClass1
.prototype
.var3
= "var3_in_Derived_prototype";
398 // One effect of 'extends' is setting up a __constructor__ member in the prototype
399 #if OUTPUT_VERSION
> 5
400 check_equals
(typeof(DerivedClass1
.prototype
.__constructor__
), 'function');
401 check
(DerivedClass1
.prototype
.hasOwnProperty
('__constructor__'));
402 check_equals
(DerivedClass1
.prototype
.__constructor__
, BaseClass1
);
403 check
(DerivedClass1
.prototype
.__constructor__
!= DerivedClass1
);
404 #else // SWF5 or below don't set __constructor__, it seems
405 check_equals
(typeof(DerivedClass1
.prototype
.__constructor__
), 'undefined');
408 check_equals
(typeof(DerivedClass1
.prototype
.constructor
), 'function');
409 check_equals
(typeof(DerivedClass1
.constructor
), 'function');
410 #if OUTPUT_VERSION
>= 6
411 check
(DerivedClass1
.prototype
.hasOwnProperty
('__proto__'));
412 check
(DerivedClass1
.prototype
.hasOwnProperty
('__constructor__'));
413 check
(DerivedClass1
.prototype
.__proto__
.hasOwnProperty
('var1'));
415 check
(! DerivedClass1
.prototype
.hasOwnProperty
('var1'));
416 check
(! DerivedClass1
.prototype
.hasOwnProperty
('var3'));
417 check_equals
(DerivedClass1
.var3
, undefined);
418 check
(! DerivedClass1
.prototype
.hasOwnProperty
('toString'));
419 check
(! DerivedClass1
.prototype
.hasOwnProperty
('valueOf'));
420 check
(! DerivedClass1
.prototype
.hasOwnProperty
('constructor'));
421 check
(DerivedClass1
.hasOwnProperty
('constructor'));
422 check_equals
(DerivedClass1
.constructor
, Function);
425 check_equals
(DerivedClass1
.prototype
.__proto__
.constructor
, BaseClass1
);
426 check_equals
(DerivedClass1
.prototype
.__proto__
, BaseClass1
.prototype
);
428 DerivedClass1
.prototype
.var2
= "var_in_Derived_prototype";
429 var obj
= new DerivedClass1
;
430 check_equals
(obj
.derivedClassCtorCalled
, 1);
431 #if OUTPUT_VERSION
> 5
432 check_equals
(typeof(obj
.__constructor__
), 'function');
433 check
(obj
.hasOwnProperty
('__constructor__'));
434 check_equals
(obj
.__constructor__
, DerivedClass1
);
435 check_equals
(obj
.__proto__
.__constructor__
, BaseClass1
);
438 // constructor of 'super' is not automatically called
439 // add 'super();' in DerivedClass1 function and see
441 check_equals
(obj
.baseClassCtorCalled
, undefined);
442 check
(obj instanceOf DerivedClass1
);
443 check
(obj instanceOf BaseClass1
);
444 check_equals
(obj
.__proto__
, DerivedClass1
.prototype
);
445 check_equals
(DerivedClass1
.prototype
.constructor
, BaseClass1
);
446 check_equals
(obj
.var1
, "var_in_Base_prototype");
447 check_equals
(obj
.var2
, "var_in_Derived_prototype");
448 check_equals
(typeof(obj
.var3
), 'undefined');
450 function MyClass
() {}
451 var proto
= MyClass
.prototype
;
452 MyClass
.prototype
.oldMember
= "overridden";
460 var myInstance
= new MyClass
();
461 check
(_root instanceOf
MovieClip);
462 check_equals
(MyClass
.prototype
.constructor
, MovieClip);
463 check_equals
(myInstance
.__proto__
, MyClass
.prototype
);
464 check_equals
(typeof(MovieClip.prototype
._x
), 'undefined');
465 check_equals
(typeof(myInstance
.oldMember
), 'undefined');
466 check_equals
(proto
.oldMember
, 'overridden');
468 #endif
// MING_SUPPORTS_ASM_EXTENDS
470 //------------------------------------------------
471 // Test access of builtin methods or getter/setter
472 // from a user-defined instance.
473 //------------------------------------------------
476 check_equals
(typeof(Date.prototype
), 'object');
477 Test
.prototype
= new Date();
479 check_equals
(typeof(t
.getYear
), 'function');
480 check_equals
(typeof(t
.setYear
), 'function');
482 check_equals
(typeof(t
.getYear
()), 'undefined');
485 t2
.__proto__
= Date.prototype
;
486 check_equals
(typeof(t2
.getYear
), 'function');
487 check_equals
(typeof(t2
.setYear
), 'function');
489 check_equals
(typeof(t2
.getYear
()), 'undefined');
492 t3
.__proto__
= MovieClip.prototype
;
493 check_equals
(typeof(t4
.gotoAndStop
), 'undefined');
494 check_equals
(typeof(t3
._currentframe
), 'undefined');
495 t3
._currentframe
= 10;
496 check_equals
(typeof(t3
._currentframe
), 'number');
499 Test3
.prototype
= new MovieClip;
501 check_equals
(typeof(t4
.gotoAndStop
), 'undefined');
502 check_equals
(typeof(t4
._currentframe
), 'undefined');
503 t4
._currentframe
= 10;
504 check_equals
(typeof(t4
._currentframe
), 'number');
506 check_equals
(typeof(_root
.gotoAndPlay
), 'function');
507 t4
.die
= _root
.gotoAndPlay
;
508 check_equals
(typeof(t4
.die
), 'function');
510 check_equals
(typeof(b
), 'undefined');
512 //------------------------------------------------
513 // Test circular inheritance
514 //------------------------------------------------
518 Test5
.__proto__
= Test4
.prototype
;
519 Test4
.__proto__
= Test5
.prototype
;
523 check
(t5 instanceOf Test5
);
524 check
(! t5 instanceOf Test4
);
525 check
(t4 instanceOf Test4
);
526 check
(! t4 instanceOf Test5
);
528 //------------------------------------------------
529 // Test implements op
530 //------------------------------------------------
532 #ifdef MING_SUPPORTS_ASM_IMPLEMENTS
536 A
.prototype
= {}; // need a prototype to set as interface of B.prototype
538 B
.prototype
= {}; // need a prototype to register interfaces on
543 push
1 // 1 interface to register
546 implements // will register A.prototype as an interface of B.prototype
550 check
(! ob
instanceof A
);
551 ob
.__proto__
= B
.prototype
;
552 check
( ob
instanceof A
);
554 // Set A.prototype as a prototype of another object
555 // and see if now ob results an instance of that other
558 check
(! ob
instanceof C
);
559 C
.prototype
= A
.prototype
;
560 check
( ob
instanceof C
);
562 #endif
// MING_SUPPORTS_ASM_IMPLEMENTS
573 PrA
.__proto__
= { vv
:8 };
576 PrB
.__proto__
= { gg
:"moo" };
580 #if OUTPUT_VERSION
> 5
582 // Check that changing __proto__.__constructor also changes super(), and the
583 // same for __proto__.__proto__
585 check_equals
(this.a
, undefined);
586 check_equals
(this.b
, undefined);
587 check_equals
(super.vv
, 8);
588 check_equals
(super.gg
, undefined);
590 this.__proto__
.__constructor__
= CtorA
;
592 check_equals
(this.a
, 4);
593 check_equals
(this.b
, undefined);
596 this.__proto__
.__constructor__
= CtorB
;
598 check_equals
(this.a
, 4);
599 check_equals
(this.b
, "string");
601 this.__proto__
.__proto__
= PrB
;
602 check_equals
(super.vv
, undefined);
603 check_equals
(super.gg
, "moo");
613 //------------------------------------------------
615 //------------------------------------------------
617 #if OUTPUT_VERSION
< 6
619 # ifdef MING_SUPPORTS_ASM_IMPLEMENTS
620 check_totals
(106 + tests
);
622 check_totals
(102 + tests
);
627 # ifdef MING_SUPPORTS_ASM_IMPLEMENTS
628 check_totals
(163 + tests
);
630 check_totals
(159 + tests
);
635 dangerousStuff
= function()
640 check
(!a
instanceof b
); // really just tests if we survive :)
644 note
("Now your flash player will try to answer the egg/chicken question. Kill it if it hangs your machine");
645 setTimeout
(dangerousStuff
, 0);