Use a weak-memory NSHashTable for referencing iterators in HTML Document

This breaks the retain cycle between the document and the attached node
iterator.

Fixes #4
This commit is contained in:
iska
2017-02-22 23:54:55 +01:00
parent 9926179a62
commit 356709a096
4 changed files with 36 additions and 2 deletions
+2 -2
View File
@@ -20,8 +20,8 @@
@interface HTMLDocument ()
{
HTMLDocument *_inertTemplateDocument;
NSMutableArray *_nodeIterators;
NSMutableArray *_ranges;
NSHashTable *_nodeIterators;
}
@property (nonatomic, assign) HTMLDocumentReadyState readyState;
@end
@@ -41,8 +41,8 @@
self = [super initWithName:@"#document" type:HTMLNodeDocument];
if (self) {
_readyState = HTMLDocumentLoading;
_nodeIterators = [NSMutableArray new];
_ranges = [NSMutableArray new];
_nodeIterators = [[NSHashTable alloc] initWithOptions:NSHashTableWeakMemory capacity:10];
}
return self;
}
+1
View File
@@ -11,5 +11,6 @@
@interface HTMLKitTestUtil : NSObject
+ (NSInvocation *)addTestToClass:(Class)cls withName:(NSString *)name block:(id)block;
+ (id)ivarForInstacne:(id)instance name:(NSString *)name;
@end
+6
View File
@@ -26,4 +26,10 @@
return invocation;
}
+ (id)ivarForInstacne:(id)instance name:(NSString *)name
{
Ivar ivar = class_getInstanceVariable([instance class], [name UTF8String]);
return object_getIvar(instance, ivar);
}
@end
+27
View File
@@ -8,6 +8,7 @@
#import <XCTest/XCTest.h>
#import "HTMLDOM.h"
#import "HTMLKitTestUtil.h"
@interface HTMLKitNodeIteratorTests : XCTestCase
@@ -565,4 +566,30 @@ static HTMLNode * (^ LastDescendant)(HTMLNode *) = ^ HTMLNode * (HTMLNode *node)
XCTAssertEqual(iterator.pointerBeforeReferenceNode, NO);
}
#pragma mark - Bug Fixes
- (void)testBugFix_Issue_4
{
HTMLDocument *document = [HTMLDocument documentWithString:@"<ul><li>1<li>2"];
NSHashTable *nodeIterators = [HTMLKitTestUtil ivarForInstacne:document name:@"_nodeIterators"];
XCTAssertTrue([nodeIterators isKindOfClass:[NSHashTable class]]);
// document.body uses an iterator internally
HTMLElement *body = document.body;
XCTAssertNotNil(body);
// iterator should be deallocated and detached at this point
XCTAssertEqual(0, nodeIterators.count);
// iterator should be autoreleased, deallocated and detached after autoreleasepool
@autoreleasepool {
HTMLNodeIterator *iterator = [[HTMLNodeIterator alloc] initWithNode:body];
[iterator nextNode];
XCTAssertEqual(1, nodeIterators.count);
}
XCTAssertEqual(0, nodeIterators.count);
}
@end