1/*
2 *   Copyright (C) 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16 *
17 */
18
19/*
20 * Zou Lunkai, zoulunkai@gmail.com
21 *
22 * Test the exact destruction time about movieclips
23 *
24 * Timeline:
25 *
26 *   Frame  | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
27 *  --------+---+---+---+---+---+---+---+
28 *   Event  |   |P J|   | R |   | * |   |
29 *
30 *  P = place (by PlaceObject2)
31 *  R = Remove (by RemoveObject2 tag)
32 *  J = jump
33 *  * = jump target
34 *
35 * Description:
36 *
37 *  frame2: DisplayObject mc1 placed at depth -16381.
38 *          mc1 has two frames, _root.gotoAndPlay(6) get executed in it's 2nd frame.
39 *  frame3:
40 *  frame4: remove DisplayObject -16381
41 *  frame6:
42 *
43 * Expected behaviour:
44 *    (1) only part of the AS in a single action_buffer(in the 2nd frame of mc1)
45 *        get executed;
46 *    (2) DisplayObject mc1 get destroied at frame 4.
47 *    (3) init actions defined in a passing-by frame get executed (while normal actions don't)
48 *
49 */
50
51
52.flash  bbox=800x600 filename="movieclip_destruction_test1.swf" background=white version=7 fps=12
53
54.frame 1
55  .action:
56   #include "Dejagnu.sc"
57  .end
58
59  // Define 3 shapes(b1, b2, b3)
60  .box b1 fill=green width=100 height=100
61  .box b2 fill=red width=100 height=100
62  .box b3 fill=yellow width=100 height=100
63
64
65.frame 2
66
67  .sprite mc1 // Define a sprite named as mc1
68    .frame 1
69      .put b1 x = 300 y = 300
70    .action:
71        note("mc1.frame1");
72    .end
73    .frame 2
74      .action:
75        note("mc1.frame2");
76        check_equals(_root.mc1.getDepth(), -16383);
77        _root.x = 0;
78        _root.gotoAndPlay(6);
79        // AS below have no chance to be executed.
80        // Since mc1 will get removed during gotoFrame above.
81        _root.x = 100;
82        _root.note("If you see this message, your player is bogus with action execution order");
83      .end
84  .end //end of sprite
85
86  .put mc1 // Place mc1
87
88  .action:
89    note("root.frame2 (after put mc1)");
90    check_equals(typeof(mc1), 'movieclip');
91    check_equals(mc1.getDepth(), -16383);
92  .end
93
94
95.frame 3
96    .action: note("root.frame3 (before definesprite)");
97    .end
98
99  .sprite mc2 // Define mc2 and add init_actions for it
100    .frame 1
101      .put b2 x = 300 y = 300
102  .end
103
104  .initaction mc2: // Add initactions for mc2(mc2 is not placed)
105    note("initaction mc2");
106    _root.initActionExecuted = "mc2";
107    // mc1 is still alive here, _root.gotoAndPlay(6) hasn't been executed yet.
108    // Note mc1 has 2 frames.
109    check_equals(typeof(mc1), 'movieclip');
110    check_equals(mc1.getDepth(), -16383);
111  .end
112
113    .action: note("root.frame3 (after initaction)");
114    .end
115
116.frame 4
117
118  .sprite mc3 // Define mc2 and add initactions for it
119    .frame 1
120      .put b3 x = 300 y = 300
121  .end
122
123    .action:
124        note("root.frame4 (before initaction)");
125        _root.check(false); // should not be executed
126    .end
127
128  .initaction mc3: // Add initactions for mc3(mc3 is not placed)
129     note("initaction mc3 in root frame4");
130    _root.initActionExecuted += ", mc3";
131    _root.check_equals(typeof(mc1), 'undefined');
132    _root.check_equals(typeof(_root.getInstanceAtDepth(-16386)), 'undefined');
133  .end
134
135  .action:
136     note("root.frame4 (after initaction)");
137     _root.check(false); // should not be executed
138  .end
139
140  .del mc1  // Remove sprite mc1
141
142  .action:
143     note("root.frame4 (after del mc1)");
144     _root.check(false); // should not be executed
145  .end
146
147
148.frame 6 // target frame
149  .action:
150    check_equals(_root.x, 0);
151  .end
152
153
154//
155// Seperate tests.
156// Test that the whole function body still get executed even when
157// 'this' object is null(removed by MovieClip.removeMovieClip()).
158.frame 8
159  .action:
160    _root.createEmptyMovieClip("mc4", 100);
161    mc4Ref = mc4;
162    check_equals(typeof(_root.mc4), 'movieclip');
163
164    mc4.func = function (clip)
165    {
166      _root.check_equals(this.valueOf(), mc4);
167      _root.testvar1 = 100;
168      // don't use clip.removeMovieClip here, to avoid bogus compiler conversion.
169      // 'removeMovieClip' is converted to lower case with the above format.
170      // This is a swf7 file.
171      clip['removeMovieClip']();
172      _root.check_equals(typeof(_root.mc4), 'undefined');
173      _root.check_equals(typeof(this), 'movieclip');
174      _root.check_equals(this.valueOf(), null);  // this pointer is null!
175      _root.testvar2 = 200;
176    };
177
178    mc4.func(mc4); // invoke the function and remove mc4
179
180    check_equals(_root.testvar1, 100);
181    check_equals(_root.testvar2, 200);
182    check_equals(typeof(_root.mc4Ref), 'movieclip');
183    check_equals(_root.mc4Ref.valueOf(), undefined);
184  .end
185
186//
187// seperate tests.
188// similar to tests in frame8, but onUnload is defined for the given movieClip
189.frame 10
190  .action:
191    _root.createEmptyMovieClip("mc5", 200);
192    check_equals(typeof(_root.mc5), 'movieclip');
193
194    mc5.onUnload = function () {}; // Define onUnload for mc5
195
196    mc5.func = function (clip)
197    {
198      _root.check_equals(this.valueOf(), mc5);
199      _root.testvar1 = 300;
200      clip['removeMovieClip']();
201      _root.check_equals(typeof(_root.mc5), 'movieclip');
202      _root.check_equals(typeof(this), 'movieclip');
203      _root.check_equals(this, _root.mc5);
204      _root.testvar2 = 400;
205    };
206
207    mc5.func(mc5); // invoke the function and remove mc5
208
209    check_equals(_root.testvar1, 300);
210    check_equals(_root.testvar2, 400);
211    check_equals(typeof(_root.mc5), 'movieclip');
212    check_equals(mc5.getDepth(), -32969);
213  .end
214
215//
216// Seperate tests for DoInitAction.
217//
218.frame 12
219  .sprite mc61  // Define a movieclip
220    .frame 1  .put b3
221  .end
222
223  .sprite mc6
224    .frame 1
225      .put mc61
226      .initaction mc61: // Add initactions for mc6
227        _root.initActionExecuted += ", mc61";
228        _root.check_equals(this, _root); // target is the root !
229      .end
230  .end
231
232  .put mc6    // Place the movieclip
233
234  .initaction mc6: // Add initactions for mc6
235    // Gnash fails by not respecting actions order for initactions
236    _root.initActionExecuted += ", mc6";
237
238
239    // Due to a bug in the proprietary player, we need to trace(__proto__) to
240    // force proper construction of the sprites.
241    _root.xcheck_equals(mc6.__proto__, Object.prototype); // returns wrong answer at first, gnash does the right thing here
242    _root.xcheck_equals(mc7.__proto__, Object.prototype); // returns wrong answer at first, gnash does the right thing here
243    trace(mc6.__proto__); trace(mc7.__proto__);
244    _root.check_equals(mc6.__proto__, MovieClip.prototype);
245    _root.check_equals(mc7.__proto__, MovieClip.prototype);
246
247    _root.check_equals(typeof(mc6), 'movieclip'); // Gnash fails because executes init actions before DLIST tags
248    _root.check_equals(typeof(mc6.mc61), 'movieclip'); // Gnash fails because executes init actions before DLIST tags
249    _root.check_equals(typeof(mc7), 'movieclip'); // Gnash fails because executes init actions before DLIST tags
250    _root.check_equals(typeof(mc7.mc71), 'movieclip'); // Gnash fails because executes init actions before DLIST tags
251    _root.check_equals(this, _root); // target is the root !
252  .end
253
254  .sprite mc71
255    .action:
256          _root.check_equals(this.__proto__, MovieClip.prototype);
257    .end
258    .frame 1  .put b3
259  .end
260
261  .sprite mc7  // Define a movieclip
262    .frame 1  .put mc71
263  .end
264
265  .put mc7    // Place the movieclip
266
267
268.frame 15
269  .initaction mc6: //Add initactions for mc6 again.
270    x = 0;
271    _root.initActionExecuted += ", mc6";
272    // This check should not be executed.
273    // We should ignore the second init actions for the same sprite.
274    // It is here just for detecting some bogus implementation
275    _root.check_equals(x, 1);
276  .end
277
278
279.frame 16
280  .sprite mc8
281  .end
282
283  .sprite mc9
284    .put mc8
285  .end
286
287  // test initactions for child sprite.
288  .initaction mc8:
289    _root.check_equals(this, _root);
290    _root.initActionExecuted += ", mc8";
291  .end
292
293  .action:
294    _root.check_equals(initActionExecuted, "mc2, mc3, mc61, mc6, mc8");
295    stop();
296    totals(39);
297  .end
298
299.end  // file end
300
301