Use "_self" as a default target for getURL when no target is given. Fixes bug #32425
[gnash.git] / testsuite / actionscript.all / Inheritance.as
blob870bf45e03bb1ec536a4eb7a2694afd28d0ae091
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
3 // Foundation, Inc
4 //
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.
9 //
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 $";
26 #include "check.as"
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);
34 #endif
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);
50 #else
51 // This is because SWF5 does not support Function class.
52 check_equals(typeof(functionObject), 'undefined');
53 #endif
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);
65 #endif
67 // functionObject is an Object, not functionObject Function,
68 // so it doesn't have functionObject 'prototype' member
69 // itself.
70 check (functionObject.prototype == undefined);
72 #if OUTPUT_VERSION > 5
73 functionObject.prototype = {a:1};
74 check_equals(functionObject.prototype.a, 1);
75 #endif
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);
81 #endif
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);
91 #endif
94 // Define the Ball constructor
95 function Ball (radius) {
96 this.radius = 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);
105 #endif
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);
113 myBall.gravity = 5;
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);
129 #endif
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);
165 #endif
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() {
234 return "A";
236 function B() { BctorCalls++; }
237 B.prototype = new A;
238 bo = new B;
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");
245 #else
246 check_equals(bo.whoami(), "A.B");
247 #endif
248 function C() {}
249 C.prototype = new B;
250 co = new C;
251 #if OUTPUT_VERSION > 6
252 check_equals(co.whoami(), "A.B");
253 #else
254 # if OUTPUT_VERSION == 6
255 check_equals(co.whoami(), "A.B.B");
256 # else
257 check_equals(co.whoami(), ".B");
258 # endif
259 #endif
260 C.prototype.whoami = function() {
261 return super.whoami()+"."+"C";
263 #if OUTPUT_VERSION > 5
264 check_equals(co.whoami(), "A.B.C");
265 #else
266 check_equals(co.whoami(), ".C");
267 #endif
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"; };
275 FctorCalls=0;
276 BctorCalls=0;
277 ActorCalls=0;
278 n = co.myName();
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
284 #endif
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);
290 #endif
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
296 #endif
298 // double gap now
299 delete A.prototype.myName;
300 FctorCalls=0;
301 BctorCalls=0;
302 ActorCalls=0;
303 n = co.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
309 #else
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);
314 #endif
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"; };
318 FctorCalls=0;
319 BctorCalls=0;
320 ActorCalls=0;
321 //note("Calling co (instanceof C) myName method");
322 n = co.myName();
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
329 #endif
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);
335 #endif
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);
341 #endif
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);
362 #endif
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);
377 #endif
379 //------------------------------------------------
380 // Test the 'extends' tag (require ming > 0.4.0.beta3)
381 //------------------------------------------------
383 // see check.as
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";
390 asm {
391 push "DerivedClass1"
392 getvariable
393 push "BaseClass1"
394 getvariable
395 extends
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');
406 #endif
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);
423 #endif
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);
436 #endif
438 // constructor of 'super' is not automatically called
439 // add 'super();' in DerivedClass1 function and see
440 // the difference
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";
453 asm {
454 push "MyClass"
455 getvariable
456 push "MovieClip"
457 getvariable
458 extends
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 //------------------------------------------------
475 function Test() {}
476 check_equals(typeof(Date.prototype), 'object');
477 Test.prototype = new Date();
478 var t = new Test;
479 check_equals(typeof(t.getYear), 'function');
480 check_equals(typeof(t.setYear), 'function');
481 t.setYear(2007);
482 check_equals(typeof(t.getYear()), 'undefined');
484 var t2 = new Object;
485 t2.__proto__ = Date.prototype;
486 check_equals(typeof(t2.getYear), 'function');
487 check_equals(typeof(t2.setYear), 'function');
488 t2.setYear(2007);
489 check_equals(typeof(t2.getYear()), 'undefined');
491 var t3 = new Object;
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');
498 function Test4() {}
499 Test3.prototype = new MovieClip;
500 var t4 = new Test4;
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');
509 var b = t4.die(4);
510 check_equals(typeof(b), 'undefined');
512 //------------------------------------------------
513 // Test circular inheritance
514 //------------------------------------------------
516 function Test5() {}
517 function Test4() {}
518 Test5.__proto__ = Test4.prototype;
519 Test4.__proto__ = Test5.prototype;
520 var t5 = new Test5;
521 var t4 = new Test4;
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
535 A = {};
536 A.prototype = {}; // need a prototype to set as interface of B.prototype
537 B = {};
538 B.prototype = {}; // need a prototype to register interfaces on
540 asm {
541 push "A"
542 getvariable
543 push 1 // 1 interface to register
544 push "B"
545 getvariable
546 implements // will register A.prototype as an interface of B.prototype
549 ob = {};
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
556 // object.. (it is)
557 C = {};
558 check (! ob instanceof C );
559 C.prototype = A.prototype;
560 check ( ob instanceof C );
562 #endif // MING_SUPPORTS_ASM_IMPLEMENTS
564 CtorA = function() {
565 this.a = 4;
568 CtorB = function() {
569 this.b = "string";
572 PrA = {};
573 PrA.__proto__ = { vv:8 };
575 PrB = {};
576 PrB.__proto__ = { gg:"moo" };
578 tests = 0;
580 #if OUTPUT_VERSION > 5
582 // Check that changing __proto__.__constructor also changes super(), and the
583 // same for __proto__.__proto__
584 Obj = function() {
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;
591 super();
592 check_equals(this.a, 4);
593 check_equals(this.b, undefined);
596 this.__proto__.__constructor__ = CtorB;
597 super();
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");
605 tests += 10;
608 Obj.prototype = PrA;
609 f = new Obj();
611 #endif
613 //------------------------------------------------
614 // END OF TEST
615 //------------------------------------------------
617 #if OUTPUT_VERSION < 6
619 # ifdef MING_SUPPORTS_ASM_IMPLEMENTS
620 check_totals(106 + tests);
621 # else
622 check_totals(102 + tests);
623 # endif
625 #else // SWF6,7,8
627 # ifdef MING_SUPPORTS_ASM_IMPLEMENTS
628 check_totals(163 + tests);
629 # else
630 check_totals(159 + tests);
631 # endif
633 #endif
635 dangerousStuff = function()
637 a = {}; b = {};
638 a.__proto__ = b;
639 b.__proto__ = a;
640 check(!a instanceof b); // really just tests if we survive :)
643 note("");
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);