Ignore:
Timestamp:
Nov 5, 2013, 2:51:52 PM (12 years ago)
Author:
[email protected]
Message:

ObjCCallbackFunctionImpl's NSInvocation shouldn't retain its target or arguments
https://bugs.webkit.org/show_bug.cgi?id=123822

Reviewed by Geoffrey Garen.

Using -retainArguments on ObjCCallbackFunctionImpl's NSInvocation leads to memory leaks.
We should handle retaining/releasing the target ourselves, and we should never retain the arguments.

  • API/ObjCCallbackFunction.mm:

(JSC::ObjCCallbackFunctionImpl::~ObjCCallbackFunctionImpl):
(JSC::ObjCCallbackFunctionImpl::name):
(objCCallbackFunctionForInvocation):
(objCCallbackFunctionForMethod):
(objCCallbackFunctionForBlock):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/ObjCCallbackFunction.mm

    r158286 r158695  
    408408    ~ObjCCallbackFunctionImpl()
    409409    {
     410        // We need to explicity release the target since we didn't call
     411        // -retainArguments on m_invocation (and we don't want to do so).
     412        if (m_type == CallbackBlock || m_type == CallbackClassMethod)
     413            [[m_invocation.get() target] release];
    410414        [m_instanceClass release];
    411415    }
     
    540544    if (m_type == CallbackInitMethod)
    541545        return class_getName(m_instanceClass);
     546    // FIXME: Maybe we could support having the selector as the name of the non-init
     547    // functions to make it a bit more user-friendly from the JS side?
    542548    return "";
    543549}
     
    664670    JSC::APIEntryShim shim(exec);
    665671    OwnPtr<JSC::ObjCCallbackFunctionImpl> impl = adoptPtr(new JSC::ObjCCallbackFunctionImpl(invocation, type, instanceClass, arguments.release(), result.release()));
    666     // FIXME: Maybe we could support having the selector as the name of the function to make it a bit more user-friendly from the JS side?
    667672    return toRef(JSC::ObjCCallbackFunction::create(exec->vm(), exec->lexicalGlobalObject(), impl->name(), impl.release()));
    668673}
     
    679684    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:types]];
    680685    [invocation setSelector:sel];
     686    // We need to retain the target Class because m_invocation doesn't retain it
     687    // by default (and we don't want it to).
    681688    if (!isInstanceMethod)
    682         [invocation setTarget:cls];
     689        [invocation setTarget:[cls retain]];
    683690    return objCCallbackFunctionForInvocation(context, invocation, isInstanceMethod ? CallbackInstanceMethod : CallbackClassMethod, isInstanceMethod ? cls : nil, _protocol_getMethodTypeEncoding(protocol, sel, YES, isInstanceMethod));
    684691}
     
    690697    const char* signature = _Block_signature(target);
    691698    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:signature]];
    692     [invocation retainArguments];
    693     id targetCopy = [target copy];
    694     [invocation setTarget:targetCopy];
    695     [targetCopy release];
     699
     700    // We don't want to use -retainArguments because that leaks memory. Arguments
     701    // would be retained indefinitely between invocations of the callback.
     702    // Additionally, we copy the target because we want the block to stick around
     703    // until the ObjCCallbackFunctionImpl is destroyed.
     704    [invocation setTarget:[target copy]];
     705
    696706    return objCCallbackFunctionForInvocation(context, invocation, CallbackBlock, nil, signature);
    697707}
Note: See TracChangeset for help on using the changeset viewer.