|
1 <!DOCTYPE HTML> |
|
2 <html> |
|
3 <!-- |
|
4 https://bugzilla.mozilla.org/show_bug.cgi?id=650295 |
|
5 --> |
|
6 <head> |
|
7 <meta charset="utf-8"> |
|
8 <title>Test for Bug 650295 -- Spin the event loop from inside a callback</title> |
|
9 <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
|
10 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> |
|
11 <script type="application/javascript" src="head.js"></script> |
|
12 </head> |
|
13 <body> |
|
14 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650295">Mozilla Bug 650295</a> |
|
15 <p id="display"></p> |
|
16 <div id="content" style="display: none"> |
|
17 |
|
18 </div> |
|
19 <pre id="test"> |
|
20 <script type="text/javascript"> |
|
21 SimpleTest.waitForExplicitFinish(); |
|
22 |
|
23 /* |
|
24 * window.showModalDialog() can be used to spin the event loop, causing |
|
25 * queued SpeechEvents (such as those created by calls to start(), stop() |
|
26 * or abort()) to be processed immediately. |
|
27 * When this is done from inside DOM event handlers, it is possible to |
|
28 * cause reentrancy in our C++ code, which we should be able to withstand. |
|
29 */ |
|
30 |
|
31 function abortAndSpinEventLoop(evt, sr) { |
|
32 sr.abort(); |
|
33 window.showModalDialog("javascript:window.close()"); |
|
34 } |
|
35 |
|
36 function doneFunc() { |
|
37 // Trigger gc now and wait some time to make sure this test gets the blame |
|
38 // for any assertions caused by showModalDialog |
|
39 // |
|
40 // NB - The assertions should be gone, but this looks too scary to touch |
|
41 // during batch cleanup. |
|
42 var count = 0, GC_COUNT = 4; |
|
43 |
|
44 function triggerGCOrFinish() { |
|
45 SpecialPowers.gc(); |
|
46 count++; |
|
47 |
|
48 if (count == GC_COUNT) { |
|
49 SimpleTest.finish(); |
|
50 } |
|
51 } |
|
52 |
|
53 for (var i = 0; i < GC_COUNT; i++) { |
|
54 setTimeout(triggerGCOrFinish, 0); |
|
55 } |
|
56 } |
|
57 |
|
58 /* |
|
59 * We start by performing a normal start, then abort from the audiostart |
|
60 * callback and force the EVENT_ABORT to be processed while still inside |
|
61 * the event handler. This causes the recording to stop, which raises |
|
62 * the audioend and (later on) end events. |
|
63 * Then, we abort (once again spinning the event loop) from the audioend |
|
64 * handler, attempting to cause a re-entry into the abort code. This second |
|
65 * call should be ignored, and we get the end callback and finish. |
|
66 */ |
|
67 |
|
68 performTest({ |
|
69 eventsToRequest: [ |
|
70 "EVENT_START", |
|
71 "EVENT_AUDIO_DATA", |
|
72 ], |
|
73 expectedEvents: { |
|
74 "audiostart": abortAndSpinEventLoop, |
|
75 "audioend": abortAndSpinEventLoop, |
|
76 "end": null |
|
77 }, |
|
78 doneFunc: doneFunc, |
|
79 prefs: [["media.webspeech.test.fake_fsm_events", true], |
|
80 ["media.webspeech.test.fake_recognition_service", true]] |
|
81 }); |
|
82 |
|
83 </script> |
|
84 </pre> |
|
85 </body> |
|
86 </html> |