Changeset 145119 in webkit


Ignore:
Timestamp:
Mar 7, 2013 12:43:05 PM (11 years ago)
Author:
mhahnenberg@apple.com
Message:

Objective-C API: Need a good way to reference event handlers without causing cycles
https://bugs.webkit.org/show_bug.cgi?id=111088

Reviewed by Geoffrey Garen.

JSManagedValue is like a special kind of weak value. When you create a JSManagedValue, you can
supply an Objective-C object as its "owner". As long as the Objective-C owner object remains
alive and its wrapper remains accessible to the JSC garbage collector (e.g. by being marked by
the global object), the reference to the JavaScript value is strong. As soon as the Objective-C
owner is deallocated or its wrapper becomes inaccessible to the garbage collector, the reference
becomes weak.

If you do not supply an owner or you use the weakValueWithValue: convenience class method, the
returned JSManagedValue behaves as a normal weak reference.

This new class allows clients to maintain references to JavaScript values in the Objective-C
heap without creating reference cycles/leaking memory.

  • API/JSAPIWrapperObject.cpp: Added.

(JSC):
(JSC::::createStructure):
(JSC::JSAPIWrapperObject::JSAPIWrapperObject): This is a special JSObject for the Objective-C API that knows
for the purposes of garbage collection/marking that it wraps an opaque Objective-C object.
(JSC::JSAPIWrapperObject::visitChildren): We add the pointer to the wrapped Objective-C object to the set of
opaque roots so that the weak handle owner for JSManagedValues can find it later.

  • API/JSAPIWrapperObject.h: Added.

(JSC):
(JSAPIWrapperObject):
(JSC::JSAPIWrapperObject::wrappedObject):
(JSC::JSAPIWrapperObject::setWrappedObject):

  • API/JSBase.cpp:

(JSSynchronousGarbageCollect):

  • API/JSBasePrivate.h:
  • API/JSCallbackObject.cpp:

(JSC):

  • API/JSCallbackObject.h:

(JSC::JSCallbackObject::destroy): Moved this to the header so that we don't get link errors with JSAPIWrapperObject.

  • API/JSContext.mm:

(-[JSContext initWithVirtualMachine:]): We weren't adding manually allocated/initialized JSVirtualMachine objects to
the global cache of virtual machines. The init methods handle this now rather than contextWithGlobalContextRef, since
not everyone is guaranteed to use the latter.
(-[JSContext initWithGlobalContextRef:]):
(+[JSContext contextWithGlobalContextRef:]):

  • API/JSManagedValue.h: Added.
  • API/JSManagedValue.mm: Added.

(JSManagedValueHandleOwner):
(managedValueHandleOwner):
(+[JSManagedValue weakValueWithValue:]):
(+[JSManagedValue managedValueWithValue:owner:]):
(-[JSManagedValue init]): We explicitly call the ARC entrypoints to initialize/get the weak owner field since we don't
use ARC when building our framework.
(-[JSManagedValue initWithValue:]):
(-[JSManagedValue initWithValue:owner:]):
(-[JSManagedValue dealloc]):
(-[JSManagedValue value]):
(-[JSManagedValue weakOwner]):
(JSManagedValueHandleOwner::isReachableFromOpaqueRoots): If the Objective-C owner is still alive (i.e. loading the weak field
returns non-nil) and that value was added to the set of opaque roots by the wrapper for that Objective-C owner, then the the
JSObject to which the JSManagedObject refers is still alive.

  • API/JSObjectRef.cpp: We have to add explicit checks for the JSAPIWrapperObject, just like the other types of JSCallbackObjects.

(JSObjectGetPrivate):
(JSObjectSetPrivate):
(JSObjectGetPrivateProperty):
(JSObjectSetPrivateProperty):
(JSObjectDeletePrivateProperty):

  • API/JSValue.mm:

(objectToValueWithoutCopy):

  • API/JSValueRef.cpp:

(JSValueIsObjectOfClass):

  • API/JSVirtualMachine.mm:

(-[JSVirtualMachine initWithContextGroupRef:]):
(+[JSVirtualMachine virtualMachineWithContextGroupRef:]):

  • API/JSWrapperMap.mm:

(wrapperFinalize):
(makeWrapper): This is our own internal version of JSObjectMake which creates JSAPIWrapperObjects, the Obj-C API
version of JSCallbackObjects.
(createObjectWithCustomBrand):
(-[JSObjCClassInfo wrapperForObject:]):
(tryUnwrapObjcObject):

  • API/JavaScriptCore.h:
  • API/tests/testapi.mm: Added new tests for the strong and weak uses of JSManagedValue in the context of an

onclick handler for an Objective-C object inserted into a JSContext.
(-[TextXYZ setWeakOnclick:]):
(-[TextXYZ setOnclick:]):
(-[TextXYZ weakOnclick]):
(-[TextXYZ onclick]):
(-[TextXYZ click]):

  • CMakeLists.txt: Various build system additions.
  • GNUmakefile.list.am:
  • JavaScriptCore.gypi:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • runtime/JSGlobalObject.cpp: Added the new canonical Structure for the JSAPIWrapperObject class.

(JSC::JSGlobalObject::reset):
(JSC):
(JSC::JSGlobalObject::visitChildren):

  • runtime/JSGlobalObject.h:

(JSGlobalObject):
(JSC::JSGlobalObject::objcWrapperObjectStructure):

Location:
trunk/Source/JavaScriptCore
Files:
4 added
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSBase.cpp

    r139541 r145119  
    111111    exec->globalData().heap.reportExtraMemoryCost(size);
    112112}
     113
     114JS_EXPORT void JSSynchronousGarbageCollectForDebugging(JSContextRef);
     115
     116void JSSynchronousGarbageCollectForDebugging(JSContextRef ctx)
     117{
     118    if (!ctx)
     119        return;
     120
     121    ExecState* exec = toJS(ctx);
     122    APIEntryShim entryShim(exec);
     123    exec->globalData().heap.collectAllGarbage();
     124}
  • trunk/Source/JavaScriptCore/API/JSCallbackObject.cpp

    r139541 r145119  
    6262}
    6363
    64 template <class Parent>
    65 void JSCallbackObject<Parent>::destroy(JSCell* cell)
    66 {
    67     static_cast<JSCallbackObject*>(cell)->JSCallbackObject::~JSCallbackObject();
    68 }
    69 
    7064void JSCallbackObjectData::finalize(Handle<Unknown> handle, void* context)
    7165{
  • trunk/Source/JavaScriptCore/API/JSCallbackObject.h

    r130612 r145119  
    137137
    138138    static const bool needsDestruction;
    139     static void destroy(JSCell*);
     139    static void destroy(JSCell* cell)
     140    {
     141        static_cast<JSCallbackObject*>(cell)->JSCallbackObject::~JSCallbackObject();
     142    }
    140143
    141144    void setPrivate(void* data);
  • trunk/Source/JavaScriptCore/API/JSContext.mm

    r144668 r145119  
    2727
    2828#import "APICast.h"
     29#import "APIShims.h"
    2930#import "JSContextInternal.h"
    3031#import "JSGlobalObject.h"
     
    7374    };
    7475
     76    [m_virtualMachine addContext:self forGlobalContextRef:m_context];
     77
    7578    return self;
    7679}
     
    188191    };
    189192
     193    [m_virtualMachine addContext:self forGlobalContextRef:m_context];
     194
    190195    return self;
    191196}
     
    255260    JSVirtualMachine *virtualMachine = [JSVirtualMachine virtualMachineWithContextGroupRef:toRef(&toJS(globalContext)->globalData())];
    256261    JSContext *context = [virtualMachine contextForGlobalContextRef:globalContext];
    257     if (!context) {
     262    if (!context)
    258263        context = [[[JSContext alloc] initWithGlobalContextRef:globalContext] autorelease];
    259         [virtualMachine addContext:context forGlobalContextRef:globalContext];
    260     }
    261264    return context;
    262265}
  • trunk/Source/JavaScriptCore/API/JSObjectRef.cpp

    r142557 r145119  
    3838#include "Identifier.h"
    3939#include "InitializeThreading.h"
     40#include "JSAPIWrapperObject.h"
    4041#include "JSArray.h"
    4142#include "JSCallbackConstructor.h"
     
    346347    if (jsObject->inherits(&JSCallbackObject<JSDestructibleObject>::s_info))
    347348        return jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->getPrivate();
     349    if (jsObject->inherits(&JSCallbackObject<JSAPIWrapperObject>::s_info))
     350        return jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->getPrivate();
    348351   
    349352    return 0;
     
    360363    if (jsObject->inherits(&JSCallbackObject<JSDestructibleObject>::s_info)) {
    361364        jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->setPrivate(data);
     365        return true;
     366    }
     367    if (jsObject->inherits(&JSCallbackObject<JSAPIWrapperObject>::s_info)) {
     368        jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivate(data);
    362369        return true;
    363370    }
     
    377384    else if (jsObject->inherits(&JSCallbackObject<JSDestructibleObject>::s_info))
    378385        result = jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->getPrivateProperty(name);
     386    else if (jsObject->inherits(&JSCallbackObject<JSAPIWrapperObject>::s_info))
     387        result = jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->getPrivateProperty(name);
    379388    return toRef(exec, result);
    380389}
     
    395404        return true;
    396405    }
     406    if (jsObject->inherits(&JSCallbackObject<JSAPIWrapperObject>::s_info)) {
     407        jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue);
     408        return true;
     409    }
    397410    return false;
    398411}
     
    410423    if (jsObject->inherits(&JSCallbackObject<JSDestructibleObject>::s_info)) {
    411424        jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->deletePrivateProperty(name);
     425        return true;
     426    }
     427    if (jsObject->inherits(&JSCallbackObject<JSAPIWrapperObject>::s_info)) {
     428        jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->deletePrivateProperty(name);
    412429        return true;
    413430    }
  • trunk/Source/JavaScriptCore/API/JSValue.mm

    r144843 r145119  
    892892            JSObjectRef result = JSObjectMakeDate(contextRef, 1, &argument, 0);
    893893            return (ObjcContainerConvertor::Task){ object, result, ContainerNone };
     894        }
     895
     896        if ([object isKindOfClass:[JSManagedValue class]]) {
     897            JSValue *value = [static_cast<JSManagedValue *>(object) value];
     898            if (!value)
     899                return (ObjcContainerConvertor::Task) { object, JSValueMakeUndefined(contextRef), ContainerNone };
     900            return (ObjcContainerConvertor::Task){ object, value->m_value, ContainerNone };
    894901        }
    895902    }
  • trunk/Source/JavaScriptCore/API/JSValueRef.cpp

    r142810 r145119  
    2929#include "APICast.h"
    3030#include "APIShims.h"
     31#include "JSAPIWrapperObject.h"
    3132#include "JSCallbackObject.h"
    3233
     
    149150        if (o->inherits(&JSCallbackObject<JSDestructibleObject>::s_info))
    150151            return jsCast<JSCallbackObject<JSDestructibleObject>*>(o)->inherits(jsClass);
     152        if (o->inherits(&JSCallbackObject<JSAPIWrapperObject>::s_info))
     153            return jsCast<JSCallbackObject<JSAPIWrapperObject>*>(o)->inherits(jsClass);
    151154    }
    152155    return false;
  • trunk/Source/JavaScriptCore/API/JSVirtualMachine.mm

    r143637 r145119  
    102102    NSPointerFunctionsOptions valueOptions = NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPersonality;
    103103    m_contextCache = [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:valueOptions capacity:0];
    104    
     104   
     105    [JSVMWrapperCache addWrapper:self forJSContextGroupRef:group];
     106 
    105107    return self;
    106108}
     
    124126{
    125127    JSVirtualMachine *virtualMachine = [JSVMWrapperCache wrapperForJSContextGroupRef:group];
    126     if (!virtualMachine) {
     128    if (!virtualMachine)
    127129        virtualMachine = [[[JSVirtualMachine alloc] initWithContextGroupRef:group] autorelease];
    128         [JSVMWrapperCache addWrapper:virtualMachine forJSContextGroupRef:group];
    129     }
    130130    return virtualMachine;
    131131}
  • trunk/Source/JavaScriptCore/API/JSWrapperMap.mm

    r144668 r145119  
    3030
    3131#import "APICast.h"
     32#import "APIShims.h"
     33#import "JSAPIWrapperObject.h"
     34#import "JSCallbackObject.h"
    3235#import "JSContextInternal.h"
    3336#import "JSWrapperMap.h"
     
    4952static void wrapperFinalize(JSObjectRef object)
    5053{
    51     [(id)JSObjectGetPrivate(object) release];
     54    JSC::JSAPIWrapperObject* wrapperObject = JSC::jsCast<JSC::JSAPIWrapperObject*>(toJS(object));
     55    [(id)wrapperObject->wrappedObject() release];
    5256}
    5357
     
    115119}
    116120
     121static JSObjectRef makeWrapper(JSContextRef ctx, JSClassRef jsClass, id wrappedObject)
     122{
     123    JSC::ExecState* exec = toJS(ctx);
     124    JSC::APIEntryShim entryShim(exec);
     125
     126    ASSERT(jsClass);
     127    JSC::JSCallbackObject<JSC::JSAPIWrapperObject>* object = JSC::JSCallbackObject<JSC::JSAPIWrapperObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->objcWrapperObjectStructure(), jsClass, 0);
     128    object->setWrappedObject(wrappedObject);
     129    if (JSC::JSObject* prototype = jsClass->prototype(exec))
     130        object->setPrototype(exec->globalData(), prototype);
     131
     132    return toRef(object);
     133}
     134
    117135// Make an object that is in all ways a completely vanilla JavaScript object,
    118136// other than that it has a native brand set that will be displayed by the default
    119137// Object.prototype.toString conversion.
    120 static JSValue *createObjectWithCustomBrand(JSContext *context, NSString *brand, JSClassRef parentClass = 0, void* privateData = 0)
     138static JSValue *createObjectWithCustomBrand(JSContext *context, NSString *brand, JSClassRef parentClass = 0, Class cls = 0)
    121139{
    122140    JSClassDefinition definition;
     
    125143    definition.parentClass = parentClass;
    126144    JSClassRef classRef = JSClassCreate(&definition);
    127     JSObjectRef result = JSObjectMake([context globalContextRef], classRef, privateData);
     145    JSObjectRef result = makeWrapper([context globalContextRef], classRef, cls);
    128146    JSClassRelease(classRef);
    129147    return [[JSValue alloc] initWithValue:result inContext:context];
     
    408426    ASSERT(!!m_prototype);
    409427
    410     JSObjectRef wrapper = JSObjectMake([m_context globalContextRef], m_classRef, [object retain]);
     428    JSObjectRef wrapper = makeWrapper([m_context globalContextRef], m_classRef, [object retain]);
    411429    JSObjectSetPrototype([m_context globalContextRef], wrapper, toRef(m_prototype.get()));
    412430    return [JSValue valueWithValue:wrapper inContext:m_context];
     
    512530    ASSERT(!exception);
    513531    if (JSValueIsObjectOfClass(context, object, wrapperClass()))
    514         return (id)JSObjectGetPrivate(object);
     532        return (id)JSC::jsCast<JSC::JSAPIWrapperObject*>(toJS(object))->wrappedObject();
    515533    if (id target = tryUnwrapBlock(context, object))
    516534        return target;
  • trunk/Source/JavaScriptCore/API/JavaScriptCore.h

    r143637 r145119  
    3434#import "JSContext.h"
    3535#import "JSValue.h"
     36#import "JSManagedValue.h"
    3637#import "JSVirtualMachine.h"
    3738#import "JSExport.h"
  • trunk/Source/JavaScriptCore/API/tests/testapi.mm

    r144489 r145119  
    2424 */
    2525
    26 #import "JavaScriptCore.h"
     26#import <JavaScriptCore/JavaScriptCore.h>
     27
     28void JSSynchronousGarbageCollectForDebugging(JSContextRef);
    2729
    2830extern "C" bool _Block_has_signature(id);
     
    102104@property int x;
    103105@property (readonly) int y;
     106@property JSValue *onclick;
     107@property JSValue *weakOnclick;
    104108- (void)test:(NSString *)message;
    105109@end
     
    109113@property int y;
    110114@property int z;
    111 @end
    112 
    113 @implementation TextXYZ
     115- (void)click;
     116@end
     117
     118@implementation TextXYZ {
     119    JSManagedValue *m_weakOnclickHandler;
     120    JSManagedValue *m_onclickHandler;
     121}
    114122@synthesize x;
    115123@synthesize y;
     
    118126{
    119127    testXYZTested = [message isEqual:@"test"] && x == 13 & y == 4 && z == 5;
     128}
     129- (void)setWeakOnclick:(JSValue *)value
     130{
     131    m_weakOnclickHandler = [JSManagedValue managedValueWithValue:value];
     132}
     133
     134- (void)setOnclick:(JSValue *)value
     135{
     136    m_onclickHandler = [JSManagedValue managedValueWithValue:value owner:self];
     137}
     138- (JSValue *)weakOnclick
     139{
     140    return [m_weakOnclickHandler value];
     141}
     142- (JSValue *)onclick
     143{
     144    return [m_onclickHandler value];
     145}
     146- (void)click
     147{
     148    if (!m_onclickHandler)
     149        return;
     150
     151    JSValue *function = [m_onclickHandler value];
     152    [function callWithArguments:[NSArray array]];
    120153}
    121154@end
     
    494527        checkResult(@"[value isEqualToObject:result]", [value isEqualToObject:result]);
    495528    }
     529
     530    @autoreleasepool {
     531        JSContext *context = [[JSContext alloc] init];
     532        TextXYZ *testXYZ = [[TextXYZ alloc] init];
     533
     534        @autoreleasepool {
     535            context[@"testXYZ"] = testXYZ;
     536
     537            [context evaluateScript:@" \
     538                didClick = false; \
     539                testXYZ.onclick = function() { \
     540                    didClick = true; \
     541                }; \
     542                 \
     543                testXYZ.weakOnclick = function() { \
     544                    return 'foo'; \
     545                }; \
     546            "];
     547        }
     548
     549        @autoreleasepool {
     550            [testXYZ click];
     551            JSValue *result = [context evaluateScript:@"didClick"];
     552            checkResult(@"Event handler onclick", [result toBool]);
     553        }
     554
     555        JSSynchronousGarbageCollectForDebugging([context globalContextRef]);
     556
     557        @autoreleasepool {
     558            JSValue *result = [context evaluateScript:@"testXYZ.onclick"];
     559            checkResult(@"onclick still around after GC", !([result isNull] || [result isUndefined]));
     560        }
     561
     562
     563        @autoreleasepool {
     564            JSValue *result = [context evaluateScript:@"testXYZ.weakOnclick"];
     565            checkResult(@"weakOnclick not around after GC", [result isNull] || [result isUndefined]);
     566        }
     567
     568        @autoreleasepool {
     569            [context evaluateScript:@" \
     570                didClick = false; \
     571                testXYZ = null; \
     572            "];
     573        }
     574
     575        JSSynchronousGarbageCollectForDebugging([context globalContextRef]);
     576
     577        @autoreleasepool {
     578            [testXYZ click];
     579            JSValue *result = [context evaluateScript:@"didClick"];
     580            checkResult(@"Event handler onclick doesn't fire", ![result toBool]);
     581        }
     582    }
    496583}
    497584
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r144910 r145119  
    2525
    2626set(JavaScriptCore_SOURCES
     27    API/JSAPIWrapperObject.cpp
    2728    API/JSBase.cpp
    2829    API/JSCallbackConstructor.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r145052 r145119  
     12013-03-05  Mark Hahnenberg  <mhahnenberg@apple.com>
     2
     3        Objective-C API: Need a good way to reference event handlers without causing cycles
     4        https://bugs.webkit.org/show_bug.cgi?id=111088
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        JSManagedValue is like a special kind of weak value. When you create a JSManagedValue, you can
     9        supply an Objective-C object as its "owner". As long as the Objective-C owner object remains
     10        alive and its wrapper remains accessible to the JSC garbage collector (e.g. by being marked by
     11        the global object), the reference to the JavaScript value is strong. As soon as the Objective-C
     12        owner is deallocated or its wrapper becomes inaccessible to the garbage collector, the reference
     13        becomes weak.
     14
     15        If you do not supply an owner or you use the weakValueWithValue: convenience class method, the
     16        returned JSManagedValue behaves as a normal weak reference.
     17
     18        This new class allows clients to maintain references to JavaScript values in the Objective-C
     19        heap without creating reference cycles/leaking memory.
     20
     21        * API/JSAPIWrapperObject.cpp: Added.
     22        (JSC):
     23        (JSC::::createStructure):
     24        (JSC::JSAPIWrapperObject::JSAPIWrapperObject): This is a special JSObject for the Objective-C API that knows
     25        for the purposes of garbage collection/marking that it wraps an opaque Objective-C object.
     26        (JSC::JSAPIWrapperObject::visitChildren): We add the pointer to the wrapped Objective-C object to the set of
     27        opaque roots so that the weak handle owner for JSManagedValues can find it later.
     28        * API/JSAPIWrapperObject.h: Added.
     29        (JSC):
     30        (JSAPIWrapperObject):
     31        (JSC::JSAPIWrapperObject::wrappedObject):
     32        (JSC::JSAPIWrapperObject::setWrappedObject):
     33        * API/JSBase.cpp:
     34        (JSSynchronousGarbageCollect):
     35        * API/JSBasePrivate.h:
     36        * API/JSCallbackObject.cpp:
     37        (JSC):
     38        * API/JSCallbackObject.h:
     39        (JSC::JSCallbackObject::destroy): Moved this to the header so that we don't get link errors with JSAPIWrapperObject.
     40        * API/JSContext.mm:
     41        (-[JSContext initWithVirtualMachine:]): We weren't adding manually allocated/initialized JSVirtualMachine objects to
     42        the global cache of virtual machines. The init methods handle this now rather than contextWithGlobalContextRef, since
     43        not everyone is guaranteed to use the latter.
     44        (-[JSContext initWithGlobalContextRef:]):
     45        (+[JSContext contextWithGlobalContextRef:]):
     46        * API/JSManagedValue.h: Added.
     47        * API/JSManagedValue.mm: Added.
     48        (JSManagedValueHandleOwner):
     49        (managedValueHandleOwner):
     50        (+[JSManagedValue weakValueWithValue:]):
     51        (+[JSManagedValue managedValueWithValue:owner:]):
     52        (-[JSManagedValue init]): We explicitly call the ARC entrypoints to initialize/get the weak owner field since we don't
     53        use ARC when building our framework.
     54        (-[JSManagedValue initWithValue:]):
     55        (-[JSManagedValue initWithValue:owner:]):
     56        (-[JSManagedValue dealloc]):
     57        (-[JSManagedValue value]):
     58        (-[JSManagedValue weakOwner]):
     59        (JSManagedValueHandleOwner::isReachableFromOpaqueRoots): If the Objective-C owner is still alive (i.e. loading the weak field
     60        returns non-nil) and that value was added to the set of opaque roots by the wrapper for that Objective-C owner, then the the
     61        JSObject to which the JSManagedObject refers is still alive.
     62        * API/JSObjectRef.cpp: We have to add explicit checks for the JSAPIWrapperObject, just like the other types of JSCallbackObjects.
     63        (JSObjectGetPrivate):
     64        (JSObjectSetPrivate):
     65        (JSObjectGetPrivateProperty):
     66        (JSObjectSetPrivateProperty):
     67        (JSObjectDeletePrivateProperty):
     68        * API/JSValue.mm:
     69        (objectToValueWithoutCopy):
     70        * API/JSValueRef.cpp:
     71        (JSValueIsObjectOfClass):
     72        * API/JSVirtualMachine.mm:
     73        (-[JSVirtualMachine initWithContextGroupRef:]):
     74        (+[JSVirtualMachine virtualMachineWithContextGroupRef:]):
     75        * API/JSWrapperMap.mm:
     76        (wrapperFinalize):
     77        (makeWrapper): This is our own internal version of JSObjectMake which creates JSAPIWrapperObjects, the Obj-C API
     78        version of JSCallbackObjects.
     79        (createObjectWithCustomBrand):
     80        (-[JSObjCClassInfo wrapperForObject:]):
     81        (tryUnwrapObjcObject):
     82        * API/JavaScriptCore.h:
     83        * API/tests/testapi.mm: Added new tests for the strong and weak uses of JSManagedValue in the context of an
     84        onclick handler for an Objective-C object inserted into a JSContext.
     85        (-[TextXYZ setWeakOnclick:]):
     86        (-[TextXYZ setOnclick:]):
     87        (-[TextXYZ weakOnclick]):
     88        (-[TextXYZ onclick]):
     89        (-[TextXYZ click]):
     90        * CMakeLists.txt: Various build system additions.
     91        * GNUmakefile.list.am:
     92        * JavaScriptCore.gypi:
     93        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
     94        * JavaScriptCore.xcodeproj/project.pbxproj:
     95        * runtime/JSGlobalObject.cpp: Added the new canonical Structure for the JSAPIWrapperObject class.
     96        (JSC::JSGlobalObject::reset):
     97        (JSC):
     98        (JSC::JSGlobalObject::visitChildren):
     99        * runtime/JSGlobalObject.h:
     100        (JSGlobalObject):
     101        (JSC::JSGlobalObject::objcWrapperObjectStructure):
     102
    11032013-03-06  Filip Pizlo  <fpizlo@apple.com>
    2104
  • trunk/Source/JavaScriptCore/GNUmakefile.list.am

    r144910 r145119  
    3737        Source/JavaScriptCore/API/APICast.h \
    3838        Source/JavaScriptCore/API/APIShims.h \
     39    Source/JavaScriptCore/API/JSAPIWrapperObject.cpp \
     40    Source/JavaScriptCore/API/JSAPIWrapperObject.h \
    3941        Source/JavaScriptCore/API/JSBase.cpp \
    4042        Source/JavaScriptCore/API/JSBasePrivate.h \
  • trunk/Source/JavaScriptCore/JavaScriptCore.gypi

    r144910 r145119  
    3737            'API/JavaScriptCore.h',
    3838            'API/JavaScript.h',
     39            'API/JSAPIWrapperObject.cpp',
     40            'API/JSAPIWrapperObject.h',
    3941            'API/JSBase.cpp',
    4042            'API/JSBase.h',
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj

    r144942 r145119  
    14191419                        </File>
    14201420                        <File
     1421                                RelativePath="..\..\API\JSAPIWrapperObject.cpp"
     1422                                >
     1423                        </File>
     1424                        <File
     1425                                RelativePath="..\..\API\JSAPIWrapperObject.h"
     1426                                >
     1427                        </File>
     1428                        <File
    14211429                                RelativePath="..\..\API\JSBase.cpp"
    14221430                                >
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r144910 r145119  
    832832                C24D31E2161CD695002AA4DB /* HeapStatistics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C24D31E0161CD695002AA4DB /* HeapStatistics.cpp */; };
    833833                C24D31E3161CD695002AA4DB /* HeapStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = C24D31E1161CD695002AA4DB /* HeapStatistics.h */; settings = {ATTRIBUTES = (Private, ); }; };
     834                C25D709B16DE99F400FCA6BC /* JSManagedValue.mm in Sources */ = {isa = PBXBuildFile; fileRef = C25D709916DE99F400FCA6BC /* JSManagedValue.mm */; };
     835                C25D709C16DE99F400FCA6BC /* JSManagedValue.h in Headers */ = {isa = PBXBuildFile; fileRef = C25D709A16DE99F400FCA6BC /* JSManagedValue.h */; settings = {ATTRIBUTES = (Public, ); }; };
    834836                C25F8BCD157544A900245B71 /* IncrementalSweeper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C25F8BCB157544A900245B71 /* IncrementalSweeper.cpp */; };
    835837                C25F8BCE157544A900245B71 /* IncrementalSweeper.h in Headers */ = {isa = PBXBuildFile; fileRef = C25F8BCC157544A900245B71 /* IncrementalSweeper.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    840842                C2C8D03014A3CEFC00578E65 /* CopiedBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C8D02E14A3CEFC00578E65 /* CopiedBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
    841843                C2C8D03114A3CEFC00578E65 /* HeapBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C8D02F14A3CEFC00578E65 /* HeapBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
     844                C2CF39C116E15A8100DD69BE /* JSAPIWrapperObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2CF39BF16E15A8100DD69BE /* JSAPIWrapperObject.cpp */; };
     845                C2CF39C216E15A8100DD69BE /* JSAPIWrapperObject.h in Headers */ = {isa = PBXBuildFile; fileRef = C2CF39C016E15A8100DD69BE /* JSAPIWrapperObject.h */; };
    842846                C2D58C3415912FEE0021A844 /* GCActivityCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D58C3315912FEE0021A844 /* GCActivityCallback.cpp */; };
    843847                C2E526BD1590EF000054E48D /* HeapTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2E526BB1590EF000054E48D /* HeapTimer.cpp */; };
     
    17281732                C24D31E0161CD695002AA4DB /* HeapStatistics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapStatistics.cpp; sourceTree = "<group>"; };
    17291733                C24D31E1161CD695002AA4DB /* HeapStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapStatistics.h; sourceTree = "<group>"; };
     1734                C25D709916DE99F400FCA6BC /* JSManagedValue.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = JSManagedValue.mm; sourceTree = "<group>"; };
     1735                C25D709A16DE99F400FCA6BC /* JSManagedValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSManagedValue.h; sourceTree = "<group>"; };
    17301736                C25F8BCB157544A900245B71 /* IncrementalSweeper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IncrementalSweeper.cpp; sourceTree = "<group>"; };
    17311737                C25F8BCC157544A900245B71 /* IncrementalSweeper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IncrementalSweeper.h; sourceTree = "<group>"; };
     
    17361742                C2C8D02E14A3CEFC00578E65 /* CopiedBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopiedBlock.h; sourceTree = "<group>"; };
    17371743                C2C8D02F14A3CEFC00578E65 /* HeapBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapBlock.h; sourceTree = "<group>"; };
     1744                C2CF39BF16E15A8100DD69BE /* JSAPIWrapperObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAPIWrapperObject.cpp; sourceTree = "<group>"; };
     1745                C2CF39C016E15A8100DD69BE /* JSAPIWrapperObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAPIWrapperObject.h; sourceTree = "<group>"; };
    17381746                C2D58C3315912FEE0021A844 /* GCActivityCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCActivityCallback.cpp; sourceTree = "<group>"; };
    17391747                C2E526BB1590EF000054E48D /* HeapTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapTimer.cpp; sourceTree = "<group>"; };
     
    22092217                                E124A8F50E555775003091F1 /* OpaqueJSString.h */,
    22102218                                5DE3D0F40DD8DDFB00468714 /* WebKitAvailability.h */,
     2219                                C25D709916DE99F400FCA6BC /* JSManagedValue.mm */,
     2220                                C25D709A16DE99F400FCA6BC /* JSManagedValue.h */,
     2221                                C2CF39BF16E15A8100DD69BE /* JSAPIWrapperObject.cpp */,
     2222                                C2CF39C016E15A8100DD69BE /* JSAPIWrapperObject.h */,
    22112223                        );
    22122224                        path = API;
     
    29252937                        buildActionMask = 2147483647;
    29262938                        files = (
     2939                                C25D709C16DE99F400FCA6BC /* JSManagedValue.h in Headers */,
    29272940                                860161E30F3A83C100F84710 /* AbstractMacroAssembler.h in Headers */,
    29282941                                0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */,
     
    31763189                                86E3C615167BABD7006D760A /* JSVirtualMachine.h in Headers */,
    31773190                                A7482E93116A7CAD003B0712 /* JSWeakObjectMapRefInternal.h in Headers */,
     3191                                C2CF39C216E15A8100DD69BE /* JSAPIWrapperObject.h in Headers */,
    31783192                                A7482B9311671147003B0712 /* JSWeakObjectMapRefPrivate.h in Headers */,
    31793193                                1442566215EDE98D0066A49B /* JSWithScope.h in Headers */,
     
    37923806                                0FF0F19E16B72A0B005DF95B /* DFGEdge.cpp in Sources */,
    37933807                                0FBC0AE71496C7C400D4FBDD /* DFGExitProfile.cpp in Sources */,
     3808                                C2CF39C116E15A8100DD69BE /* JSAPIWrapperObject.cpp in Sources */,
    37943809                                0F2BDC15151C5D4D00CD8910 /* DFGFixupPhase.cpp in Sources */,
    37953810                                86EC9DC71328DF82002B2AD7 /* DFGGraph.cpp in Sources */,
     
    40084023                                0F919D2815856773004A4E7D /* SymbolTable.cpp in Sources */,
    40094024                                A7386555118697B400540279 /* ThunkGenerators.cpp in Sources */,
     4025                                C25D709B16DE99F400FCA6BC /* JSManagedValue.mm in Sources */,
    40104026                                14A42E3F0F4F60EE00599099 /* TimeoutChecker.cpp in Sources */,
    40114027                                0FF4274A158EBE91004CB9FF /* udis86.c in Sources */,
  • trunk/Source/JavaScriptCore/Target.pri

    r144910 r145119  
    3434
    3535SOURCES += \
     36    API/JSAPIWrapperObject.cpp \
    3637    API/JSBase.cpp \
    3738    API/JSCallbackConstructor.cpp \
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r145000 r145119  
    4848#include "GetterSetter.h"
    4949#include "Interpreter.h"
     50#include "JSAPIWrapperObject.h"
    5051#include "JSActivation.h"
    5152#include "JSBoundFunction.h"
     
    230231    m_callbackConstructorStructure.set(exec->globalData(), this, JSCallbackConstructor::createStructure(exec->globalData(), this, m_objectPrototype.get()));
    231232    m_callbackObjectStructure.set(exec->globalData(), this, JSCallbackObject<JSDestructibleObject>::createStructure(exec->globalData(), this, m_objectPrototype.get()));
     233    m_objcWrapperObjectStructure.set(exec->globalData(), this, JSCallbackObject<JSAPIWrapperObject>::createStructure(exec->globalData(), this, m_objectPrototype.get()));
    232234
    233235    m_arrayPrototype.set(exec->globalData(), this, ArrayPrototype::create(exec, this, ArrayPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
     
    512514    visitor.append(&thisObject->m_callbackFunctionStructure);
    513515    visitor.append(&thisObject->m_callbackObjectStructure);
     516    visitor.append(&thisObject->m_objcWrapperObjectStructure);
    514517    visitor.append(&thisObject->m_dateStructure);
    515518    visitor.append(&thisObject->m_nullPrototypeObjectStructure);
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r145000 r145119  
    142142    WriteBarrier<Structure> m_callbackFunctionStructure;
    143143    WriteBarrier<Structure> m_callbackObjectStructure;
     144    WriteBarrier<Structure> m_objcWrapperObjectStructure;
    144145    WriteBarrier<Structure> m_dateStructure;
    145146    WriteBarrier<Structure> m_nullPrototypeObjectStructure;
     
    301302    Structure* callbackFunctionStructure() const { return m_callbackFunctionStructure.get(); }
    302303    Structure* callbackObjectStructure() const { return m_callbackObjectStructure.get(); }
     304    Structure* objcWrapperObjectStructure() const { return m_objcWrapperObjectStructure.get(); }
    303305    Structure* dateStructure() const { return m_dateStructure.get(); }
    304306    Structure* nullPrototypeObjectStructure() const { return m_nullPrototypeObjectStructure.get(); }
Note: See TracChangeset for help on using the changeset viewer.