Title: [134830] trunk
Revision
134830
Author
[email protected]
Date
2012-11-15 13:48:03 -0800 (Thu, 15 Nov 2012)

Log Message

MutationObserver wrapper should not be collected while still observing
https://bugs.webkit.org/show_bug.cgi?id=102328

Patch by Elliott Sprehn <[email protected]> on 2012-11-15
Reviewed by Adam Barth.

Source/WebCore:

Make MutationObserver an ActiveDOMObject so that the wrapper is not
collected while it is still observing the DOM. This is needed because
the wrapper is passed into the callback and expandos on the wrapper
should be preserved.

Test: fast/mutation/observer-wrapper-dropoff.html

* bindings/js/JSMutationObserverCustom.cpp:
(WebCore::JSMutationObserverConstructor::constructJSMutationObserver):
* bindings/v8/custom/V8MutationObserverCustom.cpp:
(WebCore::V8MutationObserver::constructorCallback):
* dom/MutationObserver.cpp:
(WebCore::MutationObserver::create):
(WebCore::MutationObserver::MutationObserver):
(WebCore::MutationObserver::observationStarted):
(WebCore::MutationObserver::observationEnded):
* dom/MutationObserver.h:
(WebCore):
* dom/MutationObserver.idl:

LayoutTests:

Test that a MutationObserver wrapper is not collected while the observer
is still observing since the wrapper must be passed into the callback
later.

* fast/mutation/observer-wrapper-dropoff-expected.txt: Added.
* fast/mutation/observer-wrapper-dropoff.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (134829 => 134830)


--- trunk/LayoutTests/ChangeLog	2012-11-15 21:44:22 UTC (rev 134829)
+++ trunk/LayoutTests/ChangeLog	2012-11-15 21:48:03 UTC (rev 134830)
@@ -1,3 +1,17 @@
+2012-11-15  Elliott Sprehn  <[email protected]>
+
+        MutationObserver wrapper should not be collected while still observing
+        https://bugs.webkit.org/show_bug.cgi?id=102328
+
+        Reviewed by Adam Barth.
+
+        Test that a MutationObserver wrapper is not collected while the observer
+        is still observing since the wrapper must be passed into the callback
+        later.
+
+        * fast/mutation/observer-wrapper-dropoff-expected.txt: Added.
+        * fast/mutation/observer-wrapper-dropoff.html: Added.
+
 2012-11-15  David Grogan  <[email protected]>
 
         IndexedDB: setVersion test conversion batch 6

Added: trunk/LayoutTests/fast/mutation/observer-wrapper-dropoff-expected.txt (0 => 134830)


--- trunk/LayoutTests/fast/mutation/observer-wrapper-dropoff-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/mutation/observer-wrapper-dropoff-expected.txt	2012-11-15 21:48:03 UTC (rev 134830)
@@ -0,0 +1,10 @@
+MutationObserver wrappers should survive GC for passing into the callback even if JS has lost references.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS observer.testProperty is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/mutation/observer-wrapper-dropoff.html (0 => 134830)


--- trunk/LayoutTests/fast/mutation/observer-wrapper-dropoff.html	                        (rev 0)
+++ trunk/LayoutTests/fast/mutation/observer-wrapper-dropoff.html	2012-11-15 21:48:03 UTC (rev 134830)
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+
+<script src=""
+
+<script>
+description('MutationObserver wrappers should survive GC for passing into the callback even if JS has lost references.');
+
+jsTestIsAsync = true;
+
+function addObserver(node, fn) {
+    var observer = new WebKitMutationObserver(fn);
+    observer.testProperty = true;
+    observer.observe(node, {attributes:true});
+}
+
+_onload_ = function() {
+    addObserver(document.body, function(records, observer) {
+        window.observer = observer;
+        shouldBe('observer.testProperty', 'true');
+        finishJSTest();
+    });
+
+    gc();
+
+    document.body.setAttribute('touch', 'the node');
+};
+</script>
+
+<script src=""

Modified: trunk/Source/WebCore/ChangeLog (134829 => 134830)


--- trunk/Source/WebCore/ChangeLog	2012-11-15 21:44:22 UTC (rev 134829)
+++ trunk/Source/WebCore/ChangeLog	2012-11-15 21:48:03 UTC (rev 134830)
@@ -1,3 +1,30 @@
+2012-11-15  Elliott Sprehn  <[email protected]>
+
+        MutationObserver wrapper should not be collected while still observing
+        https://bugs.webkit.org/show_bug.cgi?id=102328
+
+        Reviewed by Adam Barth.
+
+        Make MutationObserver an ActiveDOMObject so that the wrapper is not
+        collected while it is still observing the DOM. This is needed because
+        the wrapper is passed into the callback and expandos on the wrapper
+        should be preserved.
+
+        Test: fast/mutation/observer-wrapper-dropoff.html
+
+        * bindings/js/JSMutationObserverCustom.cpp:
+        (WebCore::JSMutationObserverConstructor::constructJSMutationObserver):
+        * bindings/v8/custom/V8MutationObserverCustom.cpp:
+        (WebCore::V8MutationObserver::constructorCallback):
+        * dom/MutationObserver.cpp:
+        (WebCore::MutationObserver::create):
+        (WebCore::MutationObserver::MutationObserver):
+        (WebCore::MutationObserver::observationStarted):
+        (WebCore::MutationObserver::observationEnded):
+        * dom/MutationObserver.h:
+        (WebCore):
+        * dom/MutationObserver.idl:
+
 2012-11-15  Tony Chang  <[email protected]>
 
         Generate Settings from a .in file

Modified: trunk/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp (134829 => 134830)


--- trunk/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp	2012-11-15 21:44:22 UTC (rev 134829)
+++ trunk/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp	2012-11-15 21:48:03 UTC (rev 134830)
@@ -54,8 +54,11 @@
     }
 
     JSMutationObserverConstructor* jsConstructor = jsCast<JSMutationObserverConstructor*>(exec->callee());
-    RefPtr<MutationCallback> callback = JSMutationCallback::create(object, jsConstructor->globalObject());
-    return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), MutationObserver::create(callback.release()))));
+    RefPtr<JSMutationCallback> callback = JSMutationCallback::create(object, jsConstructor->globalObject());
+    RefPtr<MutationObserver> observer = MutationObserver::create(jsConstructor->globalObject()->scriptExecutionContext(), callback);
+    JSObject* wrapper = asObject(toJS(exec, jsConstructor->globalObject(), observer.release()));
+
+    return JSValue::encode(wrapper);
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/bindings/v8/custom/V8MutationObserverCustom.cpp (134829 => 134830)


--- trunk/Source/WebCore/bindings/v8/custom/V8MutationObserverCustom.cpp	2012-11-15 21:44:22 UTC (rev 134829)
+++ trunk/Source/WebCore/bindings/v8/custom/V8MutationObserverCustom.cpp	2012-11-15 21:48:03 UTC (rev 134830)
@@ -63,7 +63,7 @@
     ScriptExecutionContext* context = getScriptExecutionContext();
 
     RefPtr<MutationCallback> callback = V8MutationCallback::create(arg, context);
-    RefPtr<MutationObserver> observer = MutationObserver::create(callback.release());
+    RefPtr<MutationObserver> observer = MutationObserver::create(context, callback.release());
 
     v8::Handle<v8::Object> wrapper = args.Holder();
     V8DOMWrapper::createDOMWrapper(observer.release(), &info, wrapper);

Modified: trunk/Source/WebCore/dom/MutationObserver.cpp (134829 => 134830)


--- trunk/Source/WebCore/dom/MutationObserver.cpp	2012-11-15 21:44:22 UTC (rev 134829)
+++ trunk/Source/WebCore/dom/MutationObserver.cpp	2012-11-15 21:48:03 UTC (rev 134830)
@@ -57,14 +57,17 @@
     }
 };
 
-PassRefPtr<MutationObserver> MutationObserver::create(PassRefPtr<MutationCallback> callback)
+PassRefPtr<MutationObserver> MutationObserver::create(ScriptExecutionContext* context, PassRefPtr<MutationCallback> callback)
 {
     ASSERT(isMainThread());
-    return adoptRef(new MutationObserver(callback));
+    RefPtr<MutationObserver> observer = adoptRef(new MutationObserver(context, callback));
+    observer->suspendIfNeeded();
+    return observer.release();
 }
 
-MutationObserver::MutationObserver(PassRefPtr<MutationCallback> callback)
-    : m_callback(callback)
+MutationObserver::MutationObserver(ScriptExecutionContext* context, PassRefPtr<MutationCallback> callback)
+    : ActiveDOMObject(context, this)
+    , m_callback(callback)
     , m_priority(s_observerPriority++)
 {
 }
@@ -138,12 +141,14 @@
 {
     ASSERT(!m_registrations.contains(registration));
     m_registrations.add(registration);
+    setPendingActivity(this);
 }
 
 void MutationObserver::observationEnded(MutationObserverRegistration* registration)
 {
     ASSERT(m_registrations.contains(registration));
     m_registrations.remove(registration);
+    unsetPendingActivity(this);
 }
 
 typedef HashSet<RefPtr<MutationObserver> > MutationObserverSet;

Modified: trunk/Source/WebCore/dom/MutationObserver.h (134829 => 134830)


--- trunk/Source/WebCore/dom/MutationObserver.h	2012-11-15 21:44:22 UTC (rev 134829)
+++ trunk/Source/WebCore/dom/MutationObserver.h	2012-11-15 21:48:03 UTC (rev 134830)
@@ -33,6 +33,7 @@
 
 #if ENABLE(MUTATION_OBSERVERS)
 
+#include "ActiveDOMObject.h"
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 #include <wtf/PassRefPtr.h>
@@ -48,13 +49,14 @@
 class MutationObserverRegistration;
 class MutationRecord;
 class Node;
+class ScriptExecutionContext;
 
 typedef int ExceptionCode;
 
 typedef unsigned char MutationObserverOptions;
 typedef unsigned char MutationRecordDeliveryOptions;
 
-class MutationObserver : public RefCounted<MutationObserver> {
+class MutationObserver : public RefCounted<MutationObserver>, public ActiveDOMObject {
 public:
     enum MutationType {
         ChildList = 1 << 0,
@@ -74,10 +76,10 @@
         CharacterDataOldValue = 1 << 6,
     };
 
-    static PassRefPtr<MutationObserver> create(PassRefPtr<MutationCallback>);
+    static PassRefPtr<MutationObserver> create(ScriptExecutionContext*, PassRefPtr<MutationCallback>);
     static void deliverAllMutations();
 
-    ~MutationObserver();
+    virtual ~MutationObserver();
 
     void observe(Node*, const Dictionary&, ExceptionCode&);
     Vector<RefPtr<MutationRecord> > takeRecords();
@@ -90,7 +92,7 @@
 private:
     struct ObserverLessThan;
 
-    explicit MutationObserver(PassRefPtr<MutationCallback>);
+    MutationObserver(ScriptExecutionContext*, PassRefPtr<MutationCallback>);
     void deliver();
 
     static bool validateOptions(MutationObserverOptions);

Modified: trunk/Source/WebCore/dom/MutationObserver.idl (134829 => 134830)


--- trunk/Source/WebCore/dom/MutationObserver.idl	2012-11-15 21:44:22 UTC (rev 134829)
+++ trunk/Source/WebCore/dom/MutationObserver.idl	2012-11-15 21:48:03 UTC (rev 134830)
@@ -29,6 +29,7 @@
  */
 
 [
+    ActiveDOMObject,
     Conditional=MUTATION_OBSERVERS,
     CustomConstructor,
     ConstructorParameters=1
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to