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