Update with current status
[gnash.git] / testsuite / actionscript.all / Object.as
blob0f03d268fdfa106b8bdb402ed0ae8b08e944932a
1 //
2 // Copyright (C) 2005, 2006, 2007, 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
20 // Test case for Object ActionScript class
21 // compile this test case with Ming makeswf, and then
22 // execute it like this gnash -1 -r 0 -v out.swf
25 rcsid="Object.as";
26 #include "check.as"
28 // Test things in Class Object (swf5~swf8)
29 check_equals(typeof(Object), 'function');
30 check_equals(typeof(Object.prototype), 'object');
31 check_equals(typeof(Object.constructor), 'function');
32 #if OUTPUT_VERSION == 5
33 check_equals(typeof(Object.__proto__), 'undefined');
34 // make Object.__proto__ visible in swf5
35 ASSetPropFlags(Object, null, 8, 128 + 1);
36 #endif
37 check_equals(typeof(Object.__proto__), 'object');
39 // registerClass is a public static function of Object
40 check_equals(typeof(Object.registerClass), 'function');
41 check_equals(Object.prototype.registerClass, undefined);
43 // Test things in Object.prototype (swf5~swf8)
44 check_equals(typeof(Object.prototype.toString), 'function');
45 check_equals(typeof(Object.prototype.toLocaleString), 'function');
46 check_equals(typeof(Object.prototype.valueOf), 'function');
47 check_equals(typeof(Object.prototype.constructor), 'function');
48 #if OUTPUT_VERSION == 5
49 check_equals(typeof(Object.prototype.addProperty), 'undefined');
50 check_equals(typeof(Object.prototype.watch), 'undefined');
51 check_equals(typeof(Object.prototype.unwatch), 'undefined');
52 check_equals(typeof(Object.prototype.isPropertyEnumerable), 'undefined');
53 check_equals(typeof(Object.prototype.isPrototypeOs), 'undefined');
54 check_equals(typeof(Object.prototype.hasOwnProperty), 'undefined');
55 // make functions above visible
56 ASSetPropFlags(Object.prototype, null, 8, 128 + 1);
57 #endif
58 // These functions are visible now even in swf5 (swf5 ~ swf8)
59 check_equals(typeof(Object.prototype.addProperty), 'function');
60 check_equals(typeof(Object.prototype.watch), 'function');
61 check_equals(typeof(Object.prototype.unwatch), 'function');
62 check_equals(typeof(Object.prototype.isPropertyEnumerable), 'function');
63 check_equals(typeof(Object.prototype.isPrototypeOf), 'function');
64 check_equals(typeof(Object.prototype.hasOwnProperty), 'function');
66 check_equals(Object.prototype.constructor, Object);
67 check_equals(typeof(Object.prototype.toString.constructor), 'function');
69 #if OUTPUT_VERSION > 5
70 // Function Object only exists in swf6 and above
71 check_equals(Object.prototype.toString.constructor, Function);
72 #else
73 check_equals(typeof(Function), 'undefined');
74 #endif
75 check_equals(Object.prototype.prototype, undefined);
77 // The bug below (no end in the inheritance chain) triggers endless
78 // recursions during run of the trace_properties() function defined
79 // in trace_properties.as from swfdec testsuite.
80 // WE WANT THIS FIXED !!
81 check_equals(Object.prototype.__proto__, undefined);
82 check(!Object.prototype.hasOwnProperty("__proto__"));
85 #if OUTPUT_VERSION > 5
87 // Through test of existance of methods!
89 check(Object.hasOwnProperty('__proto__'));
91 O = Object;
92 check_equals(O, Object);
94 // found 4 methods in Object
95 check(O.hasOwnProperty('__proto__'));
96 check(O.hasOwnProperty('registerClass'));
97 check(O.hasOwnProperty('constructor'));
98 check(O.hasOwnProperty('prototype'));
100 // fount 4 methods in Object.__proto__
101 check(O.__proto__.hasOwnProperty('__proto__'));
102 check(O.__proto__.hasOwnProperty('apply'));
103 check(O.__proto__.hasOwnProperty('call'));
104 check(O.__proto__.hasOwnProperty('constructor'));
106 check(O.__proto__ != Object.prototype);
107 check(O.__proto__.__proto__ == Object.prototype);
109 // found 3 methods in Object.constructor
110 check(O.constructor.hasOwnProperty('__proto__'));
111 check(O.constructor.hasOwnProperty('constructor'));
112 check(O.constructor.hasOwnProperty('prototype'));
114 // found 9 methods in Object.prototype
115 check(O.prototype.hasOwnProperty('addProperty'));
116 check(O.prototype.hasOwnProperty('constructor'));
117 check(O.prototype.hasOwnProperty('hasOwnProperty'));
118 check(O.prototype.hasOwnProperty('isPropertyEnumerable'));
119 check(O.prototype.hasOwnProperty('isPrototypeOf'));
120 check(O.prototype.hasOwnProperty('toString'));
121 check(O.prototype.hasOwnProperty('valueOf'));
122 check(O.prototype.hasOwnProperty('unwatch'));
123 check(O.prototype.hasOwnProperty('watch'));
125 // found 3 methods in Object.prototype.constructor
126 check(O.prototype.constructor.hasOwnProperty('__proto__'));
127 check(O.prototype.constructor.hasOwnProperty('constructor'));
128 check(O.prototype.constructor.hasOwnProperty('prototype'));
130 check_equals(O.prototype.constructor, Object);
131 check_equals(O.constructor, Function);
133 check_equals(typeof(Object.prototype.addProperty), 'function');
134 check_equals(typeof(Object.prototype.hasOwnProperty), 'function');
135 check_equals(typeof(Object.prototype.isPropertyEnumerable), 'function');
136 check_equals(typeof(Object.prototype.isPrototypeOf), 'function');
137 check_equals(typeof(Object.prototype.watch), 'function');
138 check_equals(typeof(Object.prototype.unwatch), 'function');
139 #endif
141 // Test Object creation using 'new'
142 var obj = new Object; // uses SWFACTION_NEWOBJECT
143 check (obj != undefined);
144 check_equals (typeof(obj), "object");
146 check_equals(obj.__proto__, Object.prototype);
147 check_equals(typeof(obj.prototype), 'undefined');
148 check_equals(typeof(obj.__proto__), 'object');
150 #if OUTPUT_VERSION == 5
151 check(obj.__constructor__ == undefined);
152 // make obj.__constructor__ visible
153 ASSetPropFlags(obj, null, 8, 128 + 1);
154 check(obj.__constructor__ == Object);
155 #else
156 check(obj.__constructor__ == Object);
157 #endif
159 check(obj.constructor == Object);
160 check(Object.prototype.constructor == Object);
161 check (obj.__proto__.constructor == Object);
163 // Test instantiated Object methods
164 check_equals(typeof(obj.toString), 'function');
165 check_equals(typeof(obj.valueOf), 'function');
166 check_equals(typeof(obj.addProperty), 'function');
168 check(Object.hasOwnProperty('constructor'));
169 #if OUTPUT_VERSION == 6
170 check(obj.hasOwnProperty('constructor'));
171 #elif OUTPUT_VERSION > 6
172 // seems swf7 and above are different.
173 check(!obj.hasOwnProperty('constructor'));
174 #endif
175 // swf5~8
176 check(obj.hasOwnProperty('__constructor__'));
178 // Test instantiated Object members
179 obj.member = 1;
180 check (obj.member == 1)
181 check_equals(typeof(obj.toString()), 'string');
182 check_equals(obj.toString(), '[object Object]');
183 check_equals(typeof(obj.valueOf()), 'object');
184 check_equals(obj.valueOf(), obj);
186 // Test Object creation using literal initialization
187 var obj2 = { member:1 }; // uses SWFACTION_INITOBJECT
188 check_equals(typeof(obj2), "object");
189 check_equals(typeof(obj2.__proto__), 'object');
190 check_equals(obj2.__proto__, Object.prototype);
191 check_equals(obj2.__proto__.constructor, Object);
192 check_equals(typeof(obj2.prototype), 'undefined');
195 // Test initialized object members
196 check ( obj2.member == 1 )
198 // Test Object creation using initializing constructor
199 var obj3 = new Object({ member:1 });
200 check (obj3 != undefined);
201 check (typeof(obj3) == "object");
202 check (obj3.__proto__.constructor == Object);
204 // Test initialized object members
205 check ( obj3.member != undefined );
206 check ( obj3.member == 1 );
208 // Test after-initialization members set/get
209 obj3.member2 = 3;
210 check ( obj3.member2 != undefined );
211 check ( obj3.member2 == 3 );
213 //----------------------
214 // Test copy ctors
215 //----------------------
217 var copy = new Object(obj3);
218 check_equals( copy.member2, 3 );
219 copy.test = 4;
220 check_equals( copy.test, 4 );
221 check_equals( obj3.test, 4 );
222 check (copy.__proto__.constructor == Object);
224 o = new Object("hello");
225 check_equals(o.toString(), "hello");
226 check_equals(o.valueOf(), "hello");
228 o = new Object(5);
229 check_equals(o.toString(), "5");
230 check_equals(o.valueOf(), 5);
232 o = new Object(undefined);
233 check_equals(o.toString(), "[object Object]");
234 check_equals(typeof(o.valueOf()), "object");
235 check_equals(o.valueOf(), o);
237 o = new Object(null);
238 check_equals(o.toString(), "[object Object]");
239 check_equals(typeof(o.valueOf()), "object");
240 check_equals(o.valueOf(), o);
242 //---------------------------------------------
243 // Test addProperty / hasOwnProperty (SWF6 up)
244 //---------------------------------------------
246 // Object.addProperty wasn't in SWF5
247 #if OUTPUT_VERSION > 5
249 // the 'getter' function
250 function getLen() {
251 return this._len;
254 // the 'setter' function
255 function setLen(l) {
256 this._len = l;
259 // add the "len" property
260 var ret = obj3.addProperty("len", getLen, setLen);
261 check_equals(ret, true);
263 // toString is not obj3 "own" property, but it's inherited !
264 check_equals(typeof(obj3.toString), 'function');
265 ownPropertyCheck = obj3.hasOwnProperty("toString");
266 check_equals(typeof(ownPropertyCheck), 'boolean');
267 check(!ownPropertyCheck);
269 // 'member' is an obj3 "own" member (not inherited)
270 ownPropertyCheck = obj3.hasOwnProperty("member");
271 check_equals(typeof(ownPropertyCheck), 'boolean');
272 check(ownPropertyCheck);
274 // 'len' is an obj3 "own" property (not inherited)
275 ownPropertyCheck = obj3.hasOwnProperty("len");
276 check_equals(typeof(ownPropertyCheck), 'boolean');
277 check(ownPropertyCheck);
279 check_equals (obj3.len, undefined);
280 obj3._len = 3;
281 check_equals (obj3.len, 3);
282 obj3.len = 5;
283 check_equals (obj3._len, 5);
284 check_equals (obj3.len, 5);
286 // TODO: try omitting the "setter" argument
287 var ret = obj3.addProperty("len2", getLen);
288 check_equals(ret, false);
289 check_equals (obj3.len2, undefined);
290 obj3.len2 = 'test';
291 check_equals (obj3.len2, 'test');
293 obj3.__proto__ = undefined;
294 check_equals(typeof(obj3), "object");
295 check_equals(typeof(obj3.__proto__), 'undefined');
296 check_equals(obj3, undefined);
298 // Use name of an existing property
300 o = {};
301 o.test = 5;
302 function test_get() { _root.test_get_calls++; return this.test; }
303 function test_set(v) { this.test=v; _root.test_set_calls++; }
304 test_set_calls=test_get_calls=0;
305 r = o.addProperty("test", test_get, test_set);
306 check(r);
307 check_equals(test_set_calls, 0);
308 check_equals(test_get_calls, 0);
309 test_set_calls=test_get_calls=0;
310 v = o.test;
311 check_equals(test_set_calls, 0);
312 #if OUTPUT_VERSION < 7
313 check_equals(test_get_calls, 1);
314 #else
315 xcheck_equals(test_get_calls, 65); // urgh ! :)
316 #endif
317 check_equals(v, 5); // underlying value was initializied to existing prop
318 test_set_calls=test_get_calls=0;
319 o.test = 16; // should change underlying as well I guess
320 check_equals(test_get_calls, 0);
321 #if OUTPUT_VERSION < 7
322 check_equals(test_set_calls, 1);
323 #else
324 xcheck_equals(test_set_calls, 65); // urgh ! :)
325 #endif
326 test_set_calls=test_get_calls=0;
327 r = o.addProperty("test", test_get, test_set);
328 check(r);
329 check_equals(test_get_calls, 0); // didn't invoke the former getter..
330 check_equals(test_set_calls, 0); // .. to fetch underlying var
332 test_set_calls=test_get_calls=0;
333 v = o.test;
334 // got underlying value from previous getter-setter
335 check_equals(v, 16);
336 #if OUTPUT_VERSION < 7
337 check_equals(test_get_calls, 1);
338 #else
339 xcheck_equals(test_get_calls, 65); // urgh ! :)
340 #endif
341 check_equals(test_set_calls, 0);
343 // Existing property higher in inheritance chain
345 delete o.test;
346 o2 = {};
347 o2.test = 19;
348 o.__proto__ = o2;
349 check_equals(o.test, 19);
350 r = o.addProperty("test", test_get, test_set);
351 check(r);
352 v = o.test;
353 check_equals(v, undefined); // but not existing prop from inheritance chain
355 // Existing native property
357 o = createEmptyMovieClip("hello", 10);
358 check_equals(o._target, "/hello");
359 function target_get() { _root.target_get_calls++; return this._target; }
360 function target_set(v) { this._target=v; _root.target_set_calls++; }
361 target_get_calls=target_set_calls=0;
362 ret = o.addProperty("_target", target_get, target_set);
363 check_equals(ret, true);
364 check_equals(_root.target_get_calls, 0);
365 check_equals(_root.target_set_calls, 0);
366 check_equals(typeof(o._target), "undefined"); // native getter-setter don't get initialized with underlying value
368 // Check return value.
369 ret = o.addProperty("", target_get, target_get);
370 check_equals(ret, false);
372 ret = o.addProperty("frog", 7, target_get);
373 check_equals(ret, false);
375 ret = o.addProperty("frog", "string", target_get);
376 check_equals(ret, false);
378 ret = o.addProperty("frog", target_get, target_get);
379 check_equals(ret, true);
381 ret = o.addProperty("frog", target_get, target_get);
382 check_equals(ret, true);
384 ret = o.addProperty("frog", target_get, undefined);
385 check_equals(ret, false);
387 ret = o.addProperty("frog", target_get, null);
388 check_equals(ret, true);
390 ret = o.addProperty("frog", target_get, null, "extra arg");
391 check_equals(ret, true);
393 // Try property inheritance
395 var proto = new Object();
396 check(proto.addProperty("len", getLen, setLen));
397 var inh1 = new Object();
398 inh1.__proto__ = proto;
399 var inh2 = new Object();
400 inh2.__proto__ = proto;
401 check_equals (inh1._len, undefined);
402 check_equals (inh2._len, undefined);
403 inh1.len = 4;
404 inh2.len = 9;
405 check_equals (inh1._len, 4);
406 check_equals (inh2._len, 9);
407 check_equals (proto._len, undefined);
408 inh1._len = 5;
409 inh2._len = 7;
410 check_equals (inh1.len, 5);
411 check_equals (inh2.len, 7);
412 check_equals (proto.len, undefined);
414 inh2.ogs = 5; // overridden getter-setter
415 var inh2d = new Object;
416 check(proto.addProperty("ogs", getLen, setLen));
417 inh2d.__proto__ = inh2;
418 inh2d._len = 8;
419 proto._len = 14;
422 // Inheritance is: inh2d : inh2 : proto
423 // inh2d.ogs doesn't exist at this time
424 // inh2.ogs is a normal member (value: 5)
425 // proto.ogs is a getter-setter (changes: this._len)
427 check( ! inh2d.hasOwnProperty("ogs") );
428 check( inh2d.__proto__.hasOwnProperty("ogs") );
429 check( inh2d.__proto__.__proto__.hasOwnProperty("ogs") );
430 check_equals(inh2d.ogs, 5); // find inh2.ogs
431 check_equals(inh2.ogs, 5); // find inh2.ogs
432 check_equals(inh2.__proto__.ogs, 14); // find proto.ogs
433 inh2d.ogs = 54; // sets what ?
434 check_equals(inh2d._len, 54); // this._len ! So the getter-setter takes precedence
435 check_equals(inh2d.ogs, 5); // does NOT override inh2.ogs normal member
436 check_equals(inh2.ogs, 5); // find inh2.ogs
437 check_equals(inh2.__proto__.ogs, 14); // find proto.ogs
439 // Override addProperty member
440 var o = new Object();
441 o.addProperty = function(a, b) { return a+b; };
442 var c = o.addProperty(2,5);
443 check_equals(c, 7);
444 check(o.addProperty != Object.prototype.addProperty );
446 // recursive setter
447 mem_setter = function(x)
449 this.mem2 = x;
450 this.mem = x;
452 mem_getter = function()
454 return this.mem;
456 o = {};
457 o.addProperty('mem', mem_getter, mem_setter);
458 check_equals(typeof(o.mem), 'undefined');
459 o.mem = 3; // watch out for recursion !
460 check_equals(o.mem, 3);
461 check_equals(o.mem2, 3);
463 // Test double-recursion of setter:
464 // setter1 triggers setter2
466 mem1_getter = function() { return this.mem1; };
467 mem1_setter = function(x)
469 if ( this.setterCalls > 2 )
471 return;
473 ++this.setterCalls;
474 o2.mem2 = x;
475 this.mem1 = x;
478 mem2_getter = function() { return this.mem2; };
479 mem2_setter = function(x)
481 if ( this.setterCalls > 2 )
483 return;
485 ++this.setterCalls;
486 o1.mem1 = x;
487 this.mem2 = x;
490 o1 = {}; o1.addProperty('mem1', mem1_getter, mem1_setter);
491 o2 = {}; o2.addProperty('mem2', mem2_getter, mem2_setter);
493 o1.setterCalls = o2.setterCalls = 0; // reset counters
494 o1.mem1 = 3;
495 #if OUTPUT_VERSION == 6
496 check_equals(o1.setterCalls, 1);
497 check_equals(o2.setterCalls, 1);
498 #else
499 // SWF7+ doesn't protect recursion..
500 xcheck_equals(o1.setterCalls, 3);
501 xcheck_equals(o2.setterCalls, 3);
502 #endif
503 check_equals(o1.mem1, 3);
504 check_equals(o1.mem1, 3);
506 o1.setterCalls = o2.setterCalls = 0; // reset counters
507 o2.mem2 = 6;
508 #if OUTPUT_VERSION == 6
509 check_equals(o1.setterCalls, 1);
510 check_equals(o2.setterCalls, 1);
511 #else
512 // SWF7+ doesn't protect recursion..
513 xcheck_equals(o1.setterCalls, 3);
514 xcheck_equals(o2.setterCalls, 3);
515 #endif
516 check_equals(o1.mem1, 6);
517 check_equals(o2.mem2, 6);
519 // Test having a getter but not a setter
520 getter = function() { _root.getcalls++; return this[_root.retwhat]; };
521 o = {};
522 r = o.addProperty('lmissing', getter);
523 check(!r);
524 r = o.addProperty('lundef', getter, undefined);
525 check(!r);
526 r = o.addProperty('lnull', getter, o); // self as setter..
527 check(!r);
528 r = o.addProperty('lnull', getter, null);
529 check(r);
530 getcalls=0;
531 t=o.lnull;
532 check_equals(getcalls, 1);
533 o.lnull = 5;
534 _root.retwhat='lnull';
535 check_equals(o.lnull, 5);
537 // Test having a setter but not a getter (invalid)
538 setter = function() { _root.setcalls++; };
539 o = {};
540 r = o.addProperty('lmissing', undefined, setter);
541 check(!r);
542 r = o.addProperty('lundef', null, setter);
543 check(!r);
545 // not-setting setter
546 noset_setter = function(v) { noset_setter_calls++; }; // doesn't set cache
547 simple_test_getter = function() { return this.test; };
548 o = {};
549 o.addProperty("test", simple_test_getter, noset_setter);
550 noset_setter_calls=0;
551 o.test = 2;
552 check_equals(noset_setter_calls, 1);
553 v = o.test;
554 check_equals(v, 2); // did still set the cache
555 o.test = 5;
556 check_equals(noset_setter_calls, 2);
557 v = o.test;
558 check_equals(v, 5);
560 // test setter visibility of value (multiplies * 2)
561 timetwo_test_setter = function(v) {
562 // note("timetwo_test_setter sees this.test as "+this.test);
563 this.test *= 2;
565 o = {};
566 o.test = 1;
567 o.addProperty("test", simple_test_getter, timetwo_test_setter);
568 o.test = 2;
569 v = o.test;
570 check_equals(v, 2);
571 o.test = 5;
572 v = o.test;
573 check_equals(v, 5);
576 /// more sane getter setter test
578 obj8 = {};
579 obj8_getter_cnt = 0;
580 obj8_setter_cnt = 0;
581 function obj8_getter () {
582 obj8_getter_cnt++;
583 return obj8_prop;
585 function obj8_setter (v) {
586 obj8_setter_cnt++;
587 obj8_prop = v;
589 obj8.addProperty("obj8_prop", obj8_getter, obj8_setter);
590 obj8.obj8_prop = 1;
591 v = obj8.obj8_prop;
592 check_equals(obj8_getter_cnt, 1);
593 check_equals(obj8_setter_cnt, 1);
595 obj9 = {};
596 obj9_getter_cnt = 0;
597 obj9_setter_cnt = 0;
598 function obj9_getter () {
599 obj9_getter_cnt++;
600 return this.obj9_prop_cache;
602 function obj9_setter (v) {
603 obj9_setter_cnt++;
604 this.obj9_prop_cache = v;
606 obj9.addProperty("obj9_prop", obj9_getter, obj9_setter);
607 obj9.obj9_prop = 10;
608 check_equals(obj9_getter_cnt, 0);
609 check_equals(obj9_setter_cnt, 1);
610 check_equals(obj9.obj9_prop, 10);
611 check_equals(obj9_getter_cnt, 1);
612 check_equals(obj9_setter_cnt, 1);
614 // Object.addProperty wasn't in SWF5
615 #endif // OUTPUT_VERSION > 5
617 //----------------------------------------------------
618 // Test Object.toString
619 //----------------------------------------------------
621 check_equals(Object.prototype.toString(), '[object Object]');
622 backup = Object.prototype.toString;
623 Object.prototype.toString = function() { return new Object; };
624 check_equals(typeof(Object.prototype.toString()), 'object');
625 Object.prototype.toString = function() { return new Number; };
626 check_equals(Object.prototype.toString(), 0);
627 Object.prototype.toString = backup;
629 /// This will ruin later tests while it fails hasOwnProperty.
630 //xcheck_equals(Object.prototype.toLocaleString(), '[object Object]');
631 //backup = Object.prototype.toLocaleString;
632 //Object.prototype.toLocaleString = function() { return new Object; };
633 //xcheck_equals(typeof(Object.prototype.toLocaleString()), 'object');
634 //Object.prototype.toLocaleString = function() { return new Number; };
635 //xcheck_equals(Object.prototype.toLocaleString(), 0);
636 //Object.prototype.toLocaleString = NULL;
638 // Check toLocaleString calls toString
639 backup = Object.prototype.toString;
640 Object.prototype.toString = function() { return "toString"+arguments.length; };
641 check_equals(Object.prototype.toLocaleString(1), "toString0");
642 Object.prototype.toString = backup;
644 //----------------------
645 // Test enumeration
646 //----------------------
648 function enumerate(obj, enum)
650 var enumlen = 0;
651 for (var i in obj) {
652 enum[i] = obj[i];
653 ++enumlen;
655 return enumlen;
658 var l0 = new Object({a:1, b:2});
659 var l1 = new Object({c:3, d:4});
660 l1.__proto__ = l0;
661 var l2 = new Object({e:5, f:6});
662 l2.__proto__ = l1;
664 // check properties
665 var enum = new Object;
666 var enumlen = enumerate(l2, enum);
667 #if OUTPUT_VERSION > 5
668 check_equals( enumlen, 6);
669 #endif
670 check_equals( enum["a"], 1);
671 check_equals( enum["b"], 2);
672 check_equals( enum["c"], 3);
673 check_equals( enum["d"], 4);
674 check_equals( enum["e"], 5);
675 check_equals( enum["f"], 6);
677 // Hide a property of a base object
678 var ret = ASSetPropFlags(l0, "a", 1);
680 var enum = new Object;
681 var enumlen = enumerate(l2, enum);
682 #if OUTPUT_VERSION > 5
683 check_equals( enumlen, 5);
684 #endif
686 check_equals( enum["a"], undefined);
688 var obj5 = new Object();
689 obj5['a'] = 1;
690 check_equals(obj5['a'], 1);
691 #if OUTPUT_VERSION < 7
692 check_equals(obj5['A'], 1);
693 #else
694 check_equals(obj5['A'], undefined);
695 #endif
697 //----------------------------------------------------
698 // Test Object.isPropertyEnumerable (SWF6 up)
699 //----------------------------------------------------
701 #if OUTPUT_VERSION > 5
703 // quick built-ins check
704 check( Object.prototype.hasOwnProperty("isPropertyEnumerable") );
705 check( ! Object.prototype.isPropertyEnumerable("isPropertyEnumerable") );
706 check( Object.prototype.hasOwnProperty("addProperty") );
707 check( ! Object.prototype.isPropertyEnumerable("addProperty") );
708 check( Object.prototype.hasOwnProperty("hasOwnProperty") );
709 check( ! Object.prototype.isPropertyEnumerable("hasOwnProperty") );
711 obj6 = new Object();
712 obj6.member = "a member";
714 ret = obj6.isPropertyEnumerable('unexistent');
715 check_equals(typeof(ret), 'boolean');
716 check( ! ret ); // non-existant
718 ret = obj6.isPropertyEnumerable('member');
719 check_equals(typeof(ret), 'boolean');
720 check( ret );
722 function enumerableThings()
724 this.member1 = "a string";
725 this.member2 = 3;
726 ASSetPropFlags(this, "member2", 1); // hide member2
728 enumerableThings.prototype.member3 = new Object;
730 ret = enumerableThing.isPropertyEnumerable('member1');
731 check_equals( typeof(ret), 'undefined' );
733 obj7 = new enumerableThings();
734 check( obj7.isPropertyEnumerable('member1') );
735 check( ! obj7.isPropertyEnumerable('member2') );
736 check_equals( typeof(obj7.member3), 'object' );
737 check( ! obj7.isPropertyEnumerable('member3') );
739 #endif // OUTPUT_VERSION > 5
741 //----------------------------------------------------
742 // Test Object.isPrototypeOf (SWF6 up)
743 //----------------------------------------------------
745 #if OUTPUT_VERSION > 5
747 obj8 = function() {};
748 obj9 = function() {};
749 obj9.__proto__ = new obj8;
750 obj10 = new obj9;
752 check_equals( typeof(obj8.isPrototypeOf(obj8)), 'boolean' );
753 check_equals( typeof(obj8.isPrototypeOf(undefined)), 'boolean' );
754 check( obj9.prototype.isPrototypeOf(obj10) );
755 check( ! obj8.prototype.isPrototypeOf(obj10) );
756 check( obj8.prototype.isPrototypeOf(obj9) );
757 // TODO: add tests here !
759 #endif // OUTPUT_VERSION > 5
761 //----------------------------------------------------
762 // Test Object.watch (SWF6 up)
763 //----------------------------------------------------
765 #if OUTPUT_VERSION > 5
767 o = {};
768 simplewatch = function(nam, ov, nv, d) {
769 _root.info = { nam:nam, ov:ov, nv:nv, d:d, tv:this };
770 return _root.ret;
772 r = o.watch('l', simplewatch, 'cust');
773 check(r); // can watch unexisting prop
774 _root.ret = 2;
775 o.l = 5;
776 check_equals(o.l, 2); // returned by watcher
777 check_equals(_root.info.nam, 'l');
778 check_equals(typeof(_root.info.ov), 'undefined');
779 check_equals(_root.info.nv, 5);
780 check_equals(_root.info.d, 'cust');
781 check_equals(_root.info.tv, o);
782 delete _root.info;
783 check(delete o.l);
784 o.p = 4;
785 check(!o.unwatch('p')); // can not unwatch not-watched props
786 check(!o.unwatch('r')); // can not unwatch non-watched props
787 check(o.unwatch('l')); // can unwatch non-existing but watched vars
789 // watch a getter-setter
791 get_l = function() { _root.get_l_calls++; return this.l; };
792 set_l = function(v) { _root.set_l_calls++; this.l=v; };
793 r = o.watch('l', simplewatch, 'cust2');
794 check(r);
795 check_equals(typeof(_root.info), 'undefined'); // just checking...
796 _root.ret = 'return from watch';
797 _root.get_l_calls=_root.set_l_calls=0;
798 r = o.addProperty("l", get_l, set_l);
799 check(r);
800 check_equals(_root.info.nam, 'l'); // gnash fails calling the watch trigger at all here
801 check_equals(typeof(_root.info.ov), 'undefined');
802 check_equals(typeof(_root.info.nv), 'undefined'); // underlying value of getter-setter was undefined
803 check_equals(_root.info.d, 'cust2');
804 check_equals(_root.info.tv, o);
805 check_equals(_root.get_l_calls, 0);
806 check_equals(_root.set_l_calls, 0);
808 // if a property did exist already when adding a getter-setter, it's watcher
809 // isn't called
810 delete _root.info;
811 _root.get_l_calls=_root.set_l_calls=0;
812 r = o.addProperty("l", get_l, set_l);
813 check(r);
814 check_equals(typeof(_root.info), 'undefined');
815 check_equals(_root.get_l_calls, 0);
816 check_equals(_root.set_l_calls, 0);
817 r = o.l;
818 check_equals(r, 'return from watch');
820 // Getter/setter is not invoked, but watcher was used to set it's
821 // underlying value, check this:
822 v = o.l;
823 check_equals(v, 'return from watch');
825 delete _root.info;
826 _root.get_l_calls=_root.set_l_calls=0;
828 o.l = 'ciao'; // watched, and invokes setter
829 #if OUTPUT_VERSION < 7
830 check_equals(_root.info.ov, 'return from watch'); // old value
831 xcheck_equals(_root.info.nv, 'ciao'); // we requested this
832 check_equals(_root.info.d, 'cust2');
833 check_equals(_root.info.tv, o);
834 check_equals(_root.get_l_calls, 0); // should get underlying value, not invoke getter
835 check_equals(_root.set_l_calls, 1);
836 #else
837 check_equals(_root.info.ov, 'return from watch'); // old value
838 check_equals(_root.info.nv, 'return from watch'); // mmm ?
839 check_equals(_root.info.d, 'cust2');
840 check_equals(_root.info.tv, o);
841 check_equals(_root.get_l_calls, 0); // should get underlying value, not invoke getter
842 xcheck_equals(_root.set_l_calls, 65);
843 #endif
845 r = o.unwatch("l");
846 check(!r); // can't unwatch while the property is a getter-setter
847 check(delete o.l);
848 r = o.unwatch("l");
849 check(r); // now we can unwatch.. (gnash fails as it removed the watch before)
851 // TODO: watch a getter-setter in the inheritance chain
853 //o2 = {}; o2.__proto__ = o;
854 //o2.l =
856 #endif // OUTPUT_VERSION > 5
858 //----------------------------------------------------
859 // Test Object.unwatch (SWF6 up)
860 //----------------------------------------------------
862 #if OUTPUT_VERSION > 5
864 // TODO: add tests here !
866 #endif // OUTPUT_VERSION > 5
869 nothing = new Object ();
870 nothing.toString = function() { return "toString"; };
872 check_equals ("string + " + nothing, "string + toString");
873 nothing.__proto__ = undefined;
874 #if OUTPUT_VERSION < 7
875 check_equals ("string + " + nothing, "string + ");
876 #else
877 check_equals ("string + " + nothing, "string + undefined");
878 #endif
880 nothing2 = new Object();
881 nothing2.__proto__ = undefined;
882 #if OUTPUT_VERSION < 7
883 check_equals ("string + " + nothing2, "string + ");
884 #else
885 check_equals ("string + " + nothing, "string + undefined");
886 #endif
888 nothing2.valueOf = function() { return "valueOf"; };
889 check_equals ("string + " + nothing2, "string + valueOf");
891 /// Test __resolve property
893 o = {};
894 check_equals(o.a, undefined);
895 check_equals(o.b, undefined);
897 resolveCalled = 0;
899 delete result;
901 o.__resolve = function(arg) {
902 result = arg;
903 resolveCalled++;
904 return "passed";
907 check_equals(o.a, "passed");
908 check_equals(typeof(result), "string");
909 check_equals(resolveCalled, 1);
910 check_equals(result, "a");
912 check_equals(o.b, "passed");
913 check_equals(typeof(result), "string");
914 check_equals(resolveCalled, 2);
915 check_equals(result, "b");
917 check_equals(o.quibbleDibblePropertyWithASillyName, "passed");
918 check_equals(typeof(result), "string");
919 check_equals(resolveCalled, 3);
920 check_equals(result, "quibbleDibblePropertyWithASillyName");
922 result = undefined;
924 g = {};
925 g.udef();
926 check_equals(typeof(result), "undefined");
927 check_equals(resolveCalled, 3);
929 g.__proto__ = o;
930 g.udef();
931 check_equals(typeof(result), "string");
932 check_equals(result, "udef");
933 check_equals(resolveCalled, 4);
935 check_equals(g.cips, "passed");
936 check_equals(result, "cips");
937 check_equals(resolveCalled, 5);
939 /// Check __proto__ and prototype during construction
941 TestO = function() {};
942 TestO.prototype = {};
943 TestO.prototype.toString = function() { return "hello there"; };
945 // Set to invisible in all versions up to 9.
946 ASSetPropFlags(TestO, null, 8193);
947 check_equals(TestO.prototype, undefined);
949 o = new TestO();
951 /// prototype became __proto__
952 check_equals(typeof(o.__proto__), "object");
953 check_equals(o.toString(), "hello there");
955 /// prototye is still invisible
956 check_equals(TestO.prototype, undefined);
958 /// Check DisplayObject property lookup.
960 /// Apparently no DisplayObjects are included in the prototype
961 /// recursion.
963 nonk = {};
964 nonk.__proto__ = _root;
965 _root.bobo = "hi there";
966 _root.__proto__.ubble = "U!";
968 check(!nonk._width);
969 check(!nonk.bobo);
970 check(!nonk.ubble);
972 check(nonk.__proto__._width);
973 check_equals(nonk.__proto__.bobo, "hi there");
974 check(nonk.__proto__);
976 _root.createTextField("tf", getNextHighestDepth(), 0, 0, 10, 10);
977 nonk.__proto__ = _root.tf;
978 check(nonk.__proto__);
979 check(!nonk._width);
980 check(nonk.__proto__._width);
982 // Check that running Object's constructor doesn't change __proto__.
983 // This was only because we were doing something stupid before.
985 I = function() {
986 check_equals(this.__proto__.toString(), "orig");
987 super();
988 check_equals(this.__proto__.toString(), "orig");
991 o = new Object();
992 I.prototype = o;
993 I.prototype.toString = function() { return "orig"; };
995 var tmp = new I();
997 ////////////////////////////////
999 // Messing about here with global classes may ruin later tests, so don't add
1000 // them after this.
1002 s = "hi";
1003 n = 7;
1004 b = true;
1006 delete String;
1008 o = new Object(s);
1009 check_equals(typeof(o), "undefined");
1010 o = new Object(n);
1011 check_equals(typeof(o), "object");
1012 check_equals(o.toString(), "7");
1013 o = new Object(b);
1014 check_equals(typeof(o), "object");
1015 check_equals(o.toString(), "true");
1017 delete Number;
1018 o = new Object(n);
1019 check_equals(typeof(o), "undefined");
1020 o = new Object(b);
1021 check_equals(typeof(o), "object");
1022 check_equals(o.toString(), "true");
1024 delete Boolean;
1025 o = new Object(b);
1026 check_equals(typeof(o), "undefined");
1028 #if OUTPUT_VERSION <= 5
1029 totals(139);
1030 #endif
1032 #if OUTPUT_VERSION >= 6
1033 totals(327);
1034 #endif