Title: [164088] trunk/Source/_javascript_Core
Revision
164088
Author
[email protected]
Date
2014-02-13 18:36:44 -0800 (Thu, 13 Feb 2014)

Log Message

JSManagedValue::dealloc modifies NSMapTable while iterating it
https://bugs.webkit.org/show_bug.cgi?id=128713

Reviewed by Geoffrey Garen.

Having to write a test for this revealed a bug in how addManagedReference:withOwner:
actually notifies JSManagedValues of new owners.

* API/JSManagedValue.mm:
(-[JSManagedValue dealloc]):
* API/JSVirtualMachine.mm:
(-[JSVirtualMachine addManagedReference:withOwner:]):
(-[JSVirtualMachine removeManagedReference:withOwner:]):
* API/tests/testapi.mm:
(testObjectiveCAPI):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/API/JSManagedValue.mm (164087 => 164088)


--- trunk/Source/_javascript_Core/API/JSManagedValue.mm	2014-02-14 02:32:02 UTC (rev 164087)
+++ trunk/Source/_javascript_Core/API/JSManagedValue.mm	2014-02-14 02:36:44 UTC (rev 164088)
@@ -221,11 +221,13 @@
 {
     JSVirtualMachine *virtualMachine = [[[self value] context] virtualMachine];
     if (virtualMachine) {
-        for (id owner in [m_owners keyEnumerator]) {
+        NSMapTable *copy = [m_owners copy];
+        for (id owner in [copy keyEnumerator]) {
             size_t count = reinterpret_cast<size_t>(NSMapGet(m_owners, owner));
             while (count--)
                 [virtualMachine removeManagedReference:self withOwner:owner];
         }
+        [copy release];
     }
 
     [self disconnectValue];

Modified: trunk/Source/_javascript_Core/API/JSVirtualMachine.mm (164087 => 164088)


--- trunk/Source/_javascript_Core/API/JSVirtualMachine.mm	2014-02-14 02:32:02 UTC (rev 164087)
+++ trunk/Source/_javascript_Core/API/JSVirtualMachine.mm	2014-02-14 02:36:44 UTC (rev 164088)
@@ -148,6 +148,9 @@
 
 - (void)addManagedReference:(id)object withOwner:(id)owner
 {    
+    if ([object isKindOfClass:[JSManagedValue class]])
+        [object didAddOwner:owner];
+        
     object = getInternalObjcObject(object);
     owner = getInternalObjcObject(owner);
     
@@ -166,15 +169,15 @@
         [ownedObjects release];
     }
 
-    if ([object isKindOfClass:[JSManagedValue class]])
-        [object didAddOwner:owner];
-        
     size_t count = reinterpret_cast<size_t>(NSMapGet(ownedObjects, object));
     NSMapInsert(ownedObjects, object, reinterpret_cast<void*>(count + 1));
 }
 
 - (void)removeManagedReference:(id)object withOwner:(id)owner
 {
+    if ([object isKindOfClass:[JSManagedValue class]])
+        [object didRemoveOwner:owner];
+
     object = getInternalObjcObject(object);
     owner = getInternalObjcObject(owner);
     
@@ -196,9 +199,6 @@
     if (count == 1)
         NSMapRemove(ownedObjects, object);
 
-    if ([object isKindOfClass:[JSManagedValue class]])
-        [object didRemoveOwner:owner];
-
     if (![ownedObjects count])
         [m_externalObjectGraph removeObjectForKey:owner];
 }

Modified: trunk/Source/_javascript_Core/API/tests/testapi.mm (164087 => 164088)


--- trunk/Source/_javascript_Core/API/tests/testapi.mm	2014-02-14 02:32:02 UTC (rev 164087)
+++ trunk/Source/_javascript_Core/API/tests/testapi.mm	2014-02-14 02:36:44 UTC (rev 164088)
@@ -539,6 +539,20 @@
 
     @autoreleasepool {
         JSContext *context = [[JSContext alloc] init];
+        JSValue *message = [JSValue valueWithObject:@"hello" inContext:context];
+        TestObject *rootObject = [TestObject testObject];
+        JSCollection *collection = [[JSCollection alloc] init];
+        context[@"root"] = rootObject;
+        @autoreleasepool {
+            JSValue *jsCollection = [JSValue valueWithObject:collection inContext:context];
+            JSManagedValue *weakCollection = [JSManagedValue managedValueWithValue:jsCollection andOwner:rootObject];
+            [context.virtualMachine addManagedReference:weakCollection withOwner:message];
+            JSSynchronousGarbageCollectForDebugging([context JSGlobalContextRef]);
+        }
+    }
+
+    @autoreleasepool {
+        JSContext *context = [[JSContext alloc] init];
         __block int result;
         context[@"blockCallback"] = ^(int value){
             result = value;

Modified: trunk/Source/_javascript_Core/ChangeLog (164087 => 164088)


--- trunk/Source/_javascript_Core/ChangeLog	2014-02-14 02:32:02 UTC (rev 164087)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-02-14 02:36:44 UTC (rev 164088)
@@ -1,3 +1,21 @@
+2014-02-13  Mark Hahnenberg  <[email protected]>
+
+        JSManagedValue::dealloc modifies NSMapTable while iterating it
+        https://bugs.webkit.org/show_bug.cgi?id=128713
+
+        Reviewed by Geoffrey Garen.
+
+        Having to write a test for this revealed a bug in how addManagedReference:withOwner:
+        actually notifies JSManagedValues of new owners.
+
+        * API/JSManagedValue.mm:
+        (-[JSManagedValue dealloc]):
+        * API/JSVirtualMachine.mm:
+        (-[JSVirtualMachine addManagedReference:withOwner:]):
+        (-[JSVirtualMachine removeManagedReference:withOwner:]):
+        * API/tests/testapi.mm:
+        (testObjectiveCAPI):
+
 2014-02-13  Filip Pizlo  <[email protected]>
 
         Unreviewed, fix build.
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to