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