Source/WebCore/ChangeLog

 12012-12-27 Rafael Weinstein <rafaelw@chromium.org>
 2
 3 [Mutation Observers] prevent delivery while recipient context is suspended
 4 https://bugs.webkit.org/show_bug.cgi?id=105810
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Test: inspector/debugger/mutation-observer-suspend-while-paused.html
 9
 10 * dom/MutationObserver.cpp:
 11 (WebCore::suspendedMutationObservers):
 12 (WebCore):
 13 (WebCore::MutationObserver::canDeliver):
 14 (WebCore::MutationObserver::deliver):
 15 (WebCore::MutationObserver::deliverAllMutations):
 16 * dom/MutationObserver.h:
 17
1182013-01-03 Tiancheng Jiang <tijiang@rim.com>
219
320 Update BB10 media render theme.

Source/WebCore/bindings/scripts/CodeGeneratorV8.pm

@@END
32823282 }
32833283
32843284 push(@headerContent, <<END);
 3285
 3286 virtual ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); }
32853287
32863288private:
32873289 ${v8InterfaceName}(v8::Handle<v8::Object>, ScriptExecutionContext*, v8::Handle<v8::Object>);

Source/WebCore/dom/MutationCallback.h

@@public:
4949 virtual ~MutationCallback() { }
5050
5151 virtual bool handleEvent(MutationRecordArray*, MutationObserver*) = 0;
 52 virtual ScriptExecutionContext* scriptExecutionContext() const = 0;
5253};
5354
5455}

Source/WebCore/dom/MutationObserver.cpp

@@static MutationObserverSet& activeMutationObservers()
154154 return activeObservers;
155155}
156156
 157static MutationObserverSet& suspendedMutationObservers()
 158{
 159 DEFINE_STATIC_LOCAL(MutationObserverSet, suspendedObservers, ());
 160 return suspendedObservers;
 161}
 162
157163void MutationObserver::enqueueMutationRecord(PassRefPtr<MutationRecord> mutation)
158164{
159165 ASSERT(isMainThread());

@@HashSet<Node*> MutationObserver::getObservedNodes() const
175181 return observedNodes;
176182}
177183
 184bool MutationObserver::canDeliver()
 185{
 186 return !m_callback->scriptExecutionContext()->activeDOMObjectsAreSuspended();
 187}
 188
178189void MutationObserver::deliver()
179190{
 191 ASSERT(canDeliver());
 192
180193 // Calling clearTransientRegistrations() can modify m_registrations, so it's necessary
181194 // to make a copy of the transient registrations before operating on them.
182195 Vector<MutationObserverRegistration*, 1> transientRegistrations;

@@void MutationObserver::deliverAllMutations()
204217 return;
205218 deliveryInProgress = true;
206219
 220 if (!suspendedMutationObservers().isEmpty()) {
 221 Vector<RefPtr<MutationObserver> > suspended;
 222 copyToVector(suspendedMutationObservers(), suspended);
 223 for (size_t i = 0; i < suspended.size(); ++i) {
 224 if (!suspended[i]->canDeliver())
 225 continue;
 226
 227 suspendedMutationObservers().remove(suspended[i]);
 228 activeMutationObservers().add(suspended[i]);
 229 }
 230 }
 231
207232 while (!activeMutationObservers().isEmpty()) {
208233 Vector<RefPtr<MutationObserver> > observers;
209234 copyToVector(activeMutationObservers(), observers);
210235 activeMutationObservers().clear();
211236 std::sort(observers.begin(), observers.end(), ObserverLessThan());
212  for (size_t i = 0; i < observers.size(); ++i)
213  observers[i]->deliver();
 237 for (size_t i = 0; i < observers.size(); ++i) {
 238 if (observers[i]->canDeliver())
 239 observers[i]->deliver();
 240 else
 241 suspendedMutationObservers().add(observers[i]);
 242 }
214243 }
215244
216245 deliveryInProgress = false;

Source/WebCore/dom/MutationObserver.h

@@public:
8686 void observationEnded(MutationObserverRegistration*);
8787 void enqueueMutationRecord(PassRefPtr<MutationRecord>);
8888 void setHasTransientRegistration();
 89 bool canDeliver();
8990
9091 HashSet<Node*> getObservedNodes() const;
9192

LayoutTests/ChangeLog

 12012-12-27 Rafael Weinstein <rafaelw@chromium.org>
 2
 3 [Mutation Observers] prevent delivery while recipient context is suspended
 4 https://bugs.webkit.org/show_bug.cgi?id=105810
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * inspector/debugger/mutation-observer-suspend-while-paused-expected.txt: Added.
 9 * inspector/debugger/mutation-observer-suspend-while-paused.html: Added.
 10
1112013-01-03 Csaba Osztrogonác <ossy@webkit.org>
212
313 [Qt] Unreviewed gardening, skip a new failing test.

LayoutTests/inspector/debugger/mutation-observer-suspend-while-paused-expected.txt

 1Tests that DOM Mutation Observers do not attempt to deliver mutation records while the debugger is paused.Bug 105810
 2
 3Debugger was enabled.
 4DIV and observer setup.
 5deliveryCount = 0
 6setAttribute should have triggered delivery.
 7deliveryCount = 1
 8mutateAndPause invoked.
 9Script execution paused.
 10Delivery should not have taken place.
 11deliveryCount = 1
 12Script execution resumed.
 13Second delivery should now have happened.
 14deliveryCount = 2
 15Debugger was disabled.
 16

LayoutTests/inspector/debugger/mutation-observer-suspend-while-paused.html

 1<html>
 2<head>
 3<script src="../../http/tests/inspector/inspector-test.js"></script>
 4<script src="../../http/tests/inspector/debugger-test.js"></script>
 5<script>
 6
 7var test = function()
 8{
 9 var setup =
 10 "var div = document.createElement('div');\n" +
 11 "var deliveryCount = 0;\n" +
 12 "var observer = new WebKitMutationObserver(function(records) {\n" +
 13 " deliveryCount++;\n" +
 14 "});\n" +
 15 "observer.observe(div, { attributes: true });";
 16
 17 var mutateAndPause =
 18 "function mutateAndPause() {\n" +
 19 " div.setAttribute('foo', 'baz');\n" +
 20 " debugger;\n" +
 21 "};\n" +
 22 "setTimeout(mutateAndPause, 0);";
 23
 24 InspectorTest.startDebuggerTest(step1);
 25
 26 function step1()
 27 {
 28 InspectorTest.evaluateInConsole(setup, function() {
 29 InspectorTest.addResult("DIV and observer setup.");
 30 InspectorTest.evaluateInConsoleAndDump("deliveryCount", step2);
 31 });
 32 }
 33
 34 function step2()
 35 {
 36 InspectorTest.evaluateInConsole("div.setAttribute('foo', 'bar')", function() {
 37 InspectorTest.addResult("setAttribute should have triggered delivery.");
 38 InspectorTest.evaluateInConsoleAndDump("deliveryCount", step3);
 39 });
 40 }
 41
 42 function step3()
 43 {
 44 InspectorTest.evaluateInConsole(mutateAndPause, InspectorTest.addResult.bind(InspectorTest, "mutateAndPause invoked."));
 45 InspectorTest.waitUntilPaused(step4);
 46 }
 47
 48 function step4() {
 49 InspectorTest.addResult("Delivery should not have taken place.");
 50 InspectorTest.evaluateInConsoleAndDump("deliveryCount", function() {
 51 InspectorTest.resumeExecution(step5);
 52 });
 53 }
 54
 55 function step5() {
 56 InspectorTest.addResult("Second delivery should now have happened.");
 57 InspectorTest.evaluateInConsoleAndDump("deliveryCount", InspectorTest.completeDebuggerTest);
 58 }
 59}
 60
 61</script>
 62</head>
 63
 64<body onload="runTest()">
 65<p>
 66Tests that DOM Mutation Observers do not attempt to deliver mutation records while the debugger is paused.<a href="https://bugs.webkit.org/show_bug.cgi?id=105810">Bug 105810</a>
 67</p>
 68
 69</body>
 70</html>