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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user