Changeset 135305 in webkit


Ignore:
Timestamp:
Nov 20, 2012, 11:59:14 AM (12 years ago)
Author:
commit-queue@webkit.org
Message:

Store MutationObserver callback in a hidden property for V8
https://bugs.webkit.org/show_bug.cgi?id=102555

Patch by Elliott Sprehn <esprehn@chromium.org> on 2012-11-20
Reviewed by Adam Barth.

.:

Test for reference cycle leaks with mutation observers. There doesn't seem
to be a way to check this for v8, but if you manually run you can see if it
leaks observers.

  • ManualTests/leak-cycle-observer-wrapper.html: Added.

Source/WebCore:

To prevent circular reference leaks we should store the MutationObserver
callback in a hidden property on the wrapper of the observer.

This is done by extending the code generator to support a new owner
argument to ::create() that lets you set the owner of the callback where
the hidden property should be stored.

Test: ManualTests/leak-cycle-observer-wrapper.html

  • bindings/scripts/CodeGeneratorV8.pm:

(GenerateCallbackHeader):
(GenerateCallbackImplementation):

  • bindings/scripts/test/V8/V8TestCallback.cpp: rebaselined.
  • bindings/scripts/test/V8/V8TestCallback.h: rebaselined.
  • bindings/v8/V8HiddenPropertyName.h:
  • bindings/v8/custom/V8MutationObserverCustom.cpp:

(WebCore::V8MutationObserver::constructorCallback):

Location:
trunk
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/ChangeLog

    r135281 r135305  
     12012-11-20  Elliott Sprehn  <esprehn@chromium.org>
     2
     3        Store MutationObserver callback in a hidden property for V8
     4        https://bugs.webkit.org/show_bug.cgi?id=102555
     5
     6        Reviewed by Adam Barth.
     7
     8        Test for reference cycle leaks with mutation observers. There doesn't seem
     9        to be a way to check this for v8, but if you manually run you can see if it
     10        leaks observers.
     11
     12        * ManualTests/leak-cycle-observer-wrapper.html: Added.
     13
    1142012-11-20  Carlos Garcia Campos  <cgarcia@igalia.com>
    215
  • trunk/Source/WebCore/ChangeLog

    r135303 r135305  
     12012-11-20  Elliott Sprehn  <esprehn@chromium.org>
     2
     3        Store MutationObserver callback in a hidden property for V8
     4        https://bugs.webkit.org/show_bug.cgi?id=102555
     5
     6        Reviewed by Adam Barth.
     7
     8        To prevent circular reference leaks we should store the MutationObserver
     9        callback in a hidden property on the wrapper of the observer.
     10
     11        This is done by extending the code generator to support a new owner
     12        argument to ::create() that lets you set the owner of the callback where
     13        the hidden property should be stored.
     14
     15        Test: ManualTests/leak-cycle-observer-wrapper.html
     16
     17        * bindings/scripts/CodeGeneratorV8.pm:
     18        (GenerateCallbackHeader):
     19        (GenerateCallbackImplementation):
     20        * bindings/scripts/test/V8/V8TestCallback.cpp: rebaselined.
     21        * bindings/scripts/test/V8/V8TestCallback.h: rebaselined.
     22        * bindings/v8/V8HiddenPropertyName.h:
     23        * bindings/v8/custom/V8MutationObserverCustom.cpp:
     24        (WebCore::V8MutationObserver::constructorCallback):
     25
    1262012-11-20  Abhishek Arya  <inferno@chromium.org>
    227
  • trunk/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm

    r135239 r135305  
    32473247    push(@headerContent, <<END);
    32483248public:
    3249     static PassRefPtr<${v8InterfaceName}> create(v8::Local<v8::Value> value, ScriptExecutionContext* context)
     3249    static PassRefPtr<${v8InterfaceName}> create(v8::Handle<v8::Value> value, ScriptExecutionContext* context, v8::Handle<v8::Object> owner = v8::Handle<v8::Object>())
    32503250    {
    32513251        ASSERT(value->IsObject());
    32523252        ASSERT(context);
    3253         return adoptRef(new ${v8InterfaceName}(value->ToObject(), context));
     3253        return adoptRef(new ${v8InterfaceName}(value->ToObject(), context, owner));
    32543254    }
    32553255
     
    32833283
    32843284private:
    3285     ${v8InterfaceName}(v8::Local<v8::Object>, ScriptExecutionContext*);
    3286 
     3285    ${v8InterfaceName}(v8::Handle<v8::Object>, ScriptExecutionContext*, v8::Handle<v8::Object>);
     3286
     3287    static void weakCallback(v8::Persistent<v8::Value> wrapper, void* parameter)
     3288    {
     3289        ${v8InterfaceName}* object = static_cast<${v8InterfaceName}*>(parameter);
     3290        object->m_callback.Dispose();
     3291        object->m_callback.Clear();
     3292    }
     3293
     3294    // FIXME: m_callback should be a ScopedPersistent.
    32873295    v8::Persistent<v8::Object> m_callback;
    32883296    WorldContextHandle m_worldContext;
     
    33153323    push(@implContent, "namespace WebCore {\n\n");
    33163324    push(@implContent, <<END);
    3317 ${v8InterfaceName}::${v8InterfaceName}(v8::Local<v8::Object> callback, ScriptExecutionContext* context)
     3325${v8InterfaceName}::${v8InterfaceName}(v8::Handle<v8::Object> callback, ScriptExecutionContext* context, v8::Handle<v8::Object> owner)
    33183326    : ActiveDOMCallback(context)
    33193327    , m_callback(v8::Persistent<v8::Object>::New(callback))
    33203328    , m_worldContext(UseCurrentWorld)
    33213329{
     3330    if (!owner.IsEmpty()) {
     3331        owner->SetHiddenValue(V8HiddenPropertyName::callback(), callback);
     3332        m_callback.MakeWeak(this, &${v8InterfaceName}::weakCallback);
     3333    }
    33223334}
    33233335
    33243336${v8InterfaceName}::~${v8InterfaceName}()
    33253337{
    3326     m_callback.Dispose();
     3338    if (!m_callback.IsEmpty())
     3339        m_callback.Dispose();
    33273340}
    33283341
  • trunk/Source/WebCore/bindings/scripts/test/V8/V8TestCallback.cpp

    r127972 r135305  
    4040namespace WebCore {
    4141
    42 V8TestCallback::V8TestCallback(v8::Local<v8::Object> callback, ScriptExecutionContext* context)
     42V8TestCallback::V8TestCallback(v8::Handle<v8::Object> callback, ScriptExecutionContext* context, v8::Handle<v8::Object> owner)
    4343    : ActiveDOMCallback(context)
    4444    , m_callback(v8::Persistent<v8::Object>::New(callback))
    4545    , m_worldContext(UseCurrentWorld)
    4646{
     47    if (!owner.IsEmpty()) {
     48        owner->SetHiddenValue(V8HiddenPropertyName::callback(), callback);
     49        m_callback.MakeWeak(this, &V8TestCallback::weakCallback);
     50    }
    4751}
    4852
    4953V8TestCallback::~V8TestCallback()
    5054{
    51     m_callback.Dispose();
     55    if (!m_callback.IsEmpty())
     56        m_callback.Dispose();
    5257}
    5358
  • trunk/Source/WebCore/bindings/scripts/test/V8/V8TestCallback.h

    r114502 r135305  
    3636class V8TestCallback : public TestCallback, public ActiveDOMCallback {
    3737public:
    38     static PassRefPtr<V8TestCallback> create(v8::Local<v8::Value> value, ScriptExecutionContext* context)
     38    static PassRefPtr<V8TestCallback> create(v8::Handle<v8::Value> value, ScriptExecutionContext* context, v8::Handle<v8::Object> owner = v8::Handle<v8::Object>())
    3939    {
    4040        ASSERT(value->IsObject());
    4141        ASSERT(context);
    42         return adoptRef(new V8TestCallback(value->ToObject(), context));
     42        return adoptRef(new V8TestCallback(value->ToObject(), context, owner));
    4343    }
    4444
     
    5656
    5757private:
    58     V8TestCallback(v8::Local<v8::Object>, ScriptExecutionContext*);
     58    V8TestCallback(v8::Handle<v8::Object>, ScriptExecutionContext*, v8::Handle<v8::Object>);
    5959
     60    static void weakCallback(v8::Persistent<v8::Value> wrapper, void* parameter)
     61    {
     62        V8TestCallback* object = static_cast<V8TestCallback*>(parameter);
     63        object->m_callback.Dispose();
     64        object->m_callback.Clear();
     65    }
     66
     67    // FIXME: m_callback should be a ScopedPersistent.
    6068    v8::Persistent<v8::Object> m_callback;
    6169    WorldContextHandle m_worldContext;
  • trunk/Source/WebCore/bindings/v8/V8HiddenPropertyName.h

    r134351 r135305  
    3838#define V8_HIDDEN_PROPERTIES(V) \
    3939    V(attributeListener) \
     40    V(callback) \
    4041    V(detail) \
    4142    V(document) \
  • trunk/Source/WebCore/bindings/v8/custom/V8MutationObserverCustom.cpp

    r135185 r135305  
    6262
    6363    ScriptExecutionContext* context = getScriptExecutionContext();
     64    v8::Handle<v8::Object> wrapper = args.Holder();
    6465
    65     RefPtr<MutationCallback> callback = V8MutationCallback::create(arg, context);
     66    RefPtr<MutationCallback> callback = V8MutationCallback::create(arg, context, wrapper);
    6667    RefPtr<MutationObserver> observer = MutationObserver::create(callback.release());
    6768
    68     v8::Handle<v8::Object> wrapper = args.Holder();
    6969    V8DOMWrapper::createDOMWrapper(observer.release(), &info, wrapper);
    7070    return wrapper;
Note: See TracChangeset for help on using the changeset viewer.