Source/WebCore/ChangeLog

 12011-09-27 Eugene Nalimov <enal@chromium.org>
 2
 3 Playing HTMLAudioElement can be garbage collected
 4 https://bugs.webkit.org/show_bug.cgi?id=66878
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Fix consists of 2 parts:
 9 (a) make HTMLAudioElement an 'active' one, meaning that it cannot be
 10 garbage collected if it has panding activity
 11 (b) fix v8 bindings bug that was in the code forever, event listener
 12 could be garbage collected even if object it attached to is still
 13 alive, resulting in the loss of events.
 14
 15 Submitting both fixes together because without 2nd fix I could not
 16 programmatically test 1st fix -- test has to depend on the events.
 17
 18 Test: media/audio-garbage-collect.html
 19
 20 * bindings/scripts/CodeGeneratorV8.pm:
 21 (GenerateEventListenerCallback):
 22 (IsActiveDomType):
 23 * bindings/v8/custom/V8HTMLAudioElementConstructor.cpp:
 24 (WebCore::v8HTMLAudioElementConstructorCallback):
 25 * html/HTMLAudioElement.h:
 26 (WebCore::HTMLAudioElement::hasPendingActivity):
 27 * html/HTMLMediaElement.h:
 28
1292011-10-11 Pavel Feldman <pfeldman@google.com>
230
331 Web Inspector: make Extensions component compile.
97152

Source/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp

4747
4848namespace WebCore {
4949
50 WrapperTypeInfo V8HTMLAudioElementConstructor::info = { V8HTMLAudioElementConstructor::GetTemplate, 0, 0, 0 };
 50WrapperTypeInfo V8HTMLAudioElementConstructor::info = { V8HTMLAudioElementConstructor::GetTemplate, V8HTMLAudioElement::derefObject, V8HTMLAudioElement::toActiveDOMObject, 0 };
5151
5252static v8::Handle<v8::Value> v8HTMLAudioElementConstructorCallback(const v8::Arguments& args)
5353{

@@static v8::Handle<v8::Value> v8HTMLAudio
6868 // may end up being the only node in the map and get garbage-collected prematurely.
6969 toV8(document);
7070
71 
7271 String src;
7372 if (args.Length() > 0)
7473 src = toWebCoreString(args[0]);

@@static v8::Handle<v8::Value> v8HTMLAudio
7675
7776 V8DOMWrapper::setDOMWrapper(args.Holder(), &V8HTMLAudioElementConstructor::info, audio.get());
7877 audio->ref();
79  V8DOMWrapper::setJSWrapperForDOMNode(audio.get(), v8::Persistent<v8::Object>::New(args.Holder()));
 78 V8DOMWrapper::setJSWrapperForActiveDOMObject(audio.get(), v8::Persistent<v8::Object>::New(args.Holder()));
8079 return args.Holder();
8180}
8281
97152

Source/WebCore/html/HTMLAudioElement.h

@@public:
4040 static PassRefPtr<HTMLAudioElement> create(const QualifiedName&, Document*);
4141 static PassRefPtr<HTMLAudioElement> createForJSConstructor(Document*, const String& src);
4242
 43 virtual bool hasPendingActivity() const { return isPlaying() || HTMLMediaElement::hasPendingActivity(); }
 44
4345private:
4446 HTMLAudioElement(const QualifiedName&, Document*);
4547
97152

Source/WebCore/html/HTMLAudioElement.idl

2525
2626module html {
2727 interface [
 28 ActiveDOMObject,
2829 Conditional=VIDEO
2930 ] HTMLAudioElement : HTMLMediaElement {
3031
97152

Source/WebCore/html/HTMLMediaElement.h

@@class Widget;
5858// But it can't be until the Chromium WebMediaPlayerClientImpl class is fixed so it
5959// no longer depends on typecasting a MediaPlayerClient to an HTMLMediaElement.
6060
61 class HTMLMediaElement : public HTMLElement, public MediaPlayerClient, private MediaCanStartListener, private ActiveDOMObject {
 61class HTMLMediaElement : public HTMLElement, public MediaPlayerClient, private MediaCanStartListener, public ActiveDOMObject {
6262public:
6363 MediaPlayer* player() const { return m_player.get(); }
6464

@@public:
205205
206206 bool isPlaying() const { return m_playing; }
207207
 208 virtual bool hasPendingActivity() const;
 209
208210#if ENABLE(WEB_AUDIO)
209211 MediaElementAudioSourceNode* audioSourceNode() { return m_audioSourceNode; }
210212 void setAudioSourceNode(MediaElementAudioSourceNode*);

@@private:
268270 virtual void suspend(ReasonForSuspension);
269271 virtual void resume();
270272 virtual void stop();
271  virtual bool hasPendingActivity() const;
272273
273274 virtual void mediaVolumeDidChange();
274275
97152

LayoutTests/ChangeLog

 12011-09-27 Eugene Nalimov <enal@chromium.org>
 2
 3 Playing HTMLAudioElement can be garbage collected
 4 https://bugs.webkit.org/show_bug.cgi?id=66878
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Added regression test that plays short audio (~1 second) several times
 9 in a row and causes garbage collector in parallel. Test should play
 10 audio stream specified number of times and signal 'ended' event.
 11
 12 * media/audio-garbage-collect-expected.txt: Added.
 13 * media/audio-garbage-collect.html: Added.
 14 * media/content/click2.wav: Added.
 15
1162011-10-05 Pavel Podivilov <podivilov@chromium.org>
217
318 Web Inspector: implement CompilerSourceMappingProvider.
97152

LayoutTests/fast/xpath/xpath-result-eventlistener-crash.html

@@function allocate() {
2626
2727 // Fill the heap with event listeners...
2828 var a = []
29  for (var i = 0; i < 5000; ++i)
 29 for (var i = 0; i < 2000; ++i)
3030 a[a.length] = function() { };
3131
3232 // ...followed by a DOM node wrapper
97152

LayoutTests/media/audio-garbage-collect-expected.txt

 1Tests that we don't garbage collect playing audio object or event listener.
 2
 3According to http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html,
 4"4.8.10.8 Playing the media resource",
 5"Media elements must not stop playing just because all references to them have been removed; only once a media element is in a state where no further audio could ever be played by that element may the element be garbage collected."
 6
 7(see https://bugs.webkit.org/show_bug.cgi?id=66878 and http://crbug.com/62604 for more details).
 8
 9PASS
 10
 11
0

LayoutTests/media/audio-garbage-collect.html

 1<!DOCTYPE HTML>
 2
 3<html>
 4<body>
 5
 6<p>Tests that we don't garbage collect playing audio object or event listener.</p>
 7<p>According to http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html,<br />
 8"4.8.10.8 Playing the media resource",<br />
 9"Media elements must not stop playing just because all references to them have
 10been removed; only once a media element is in a state where no further audio
 11could ever be played by that element may the element be garbage collected."<br /><br />
 12(see https://bugs.webkit.org/show_bug.cgi?id=66878 and http://crbug.com/62604 for more details).</p>
 13<p id="result">
 14 FAIL: Test either still running or stopped prematurely.
 15</p>
 16
 17<script src=media-file.js></script>
 18<script src=video-test.js></script>
 19<script type="text/javascript">
 20
 21var num_players = 4;
 22var play_times = 5;
 23
 24var a;
 25var num_played;
 26var total_played = 0;
 27
 28function forceGC() {
 29 if (window.GCController)
 30 return GCController.collect();
 31
 32 // Force garbage collection
 33 for (var ndx = 0; ndx < 99000; ndx ++)
 34 var str = new String("1234");
 35}
 36
 37function finish() {
 38 document.getElementById("result").innerText = "PASS";
 39 if (window.layoutTestController) {
 40 layoutTestController.notifyDone();
 41 }
 42}
 43
 44function start() {
 45 num_played = 0;
 46 var audioFile = findMediaFile("audio", "content/click2");
 47 a = new Audio(audioFile);
 48 a.addEventListener('ended', function() {
 49 num_played ++;
 50 if (num_played < play_times) {
 51 a.currentTime = 0;
 52 a.play();
 53 if (num_played == play_times - 1) {
 54 a = null;
 55 forceGC();
 56 }
 57 } else {
 58 total_played ++;
 59 if (total_played < num_players)
 60 start();
 61 else
 62 finish();
 63 }
 64 });
 65 a.addEventListener('canplaythrough', function() {
 66 a.play();
 67 });
 68}
 69
 70start();
 71
 72</script>
 73
 74</body>
 75</html>
0

LayoutTests/media/content/click2.wav

Binary file, nothing to see here