diff --git a/.jazzy.yaml b/.jazzy.yaml index 4b28c93..4bcae51 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -1,5 +1,5 @@ module: HTMLKit -module_version: 2.0.4 +module_version: 2.0.5 author: Iskandar Abudiab author_url: https://twitter.com/iabudiab github_url: https://github.com/iabudiab/HTMLKit diff --git a/CHANGELOG.md b/CHANGELOG.md index 87aa529..4f67a6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Change Log +## [2.0.5](https://github.com/iabudiab/HTMLKit/releases/tag/2.0.5) + +Released on 2017.04.19 + +### Fixed +- Xcode 8.3 issue with modulemaps + - Temporary workaround (renamed modulemap file) +- Memory Leaks in `CSSInputStream` + +### Added +- Minor memory consumption improvements + - Collections for child nodes or attributes of HTML Nodes or Elements are allocated lazily + - Underyling data string of `CharacterData` is allocated on first access + - Autorelease pool for the main `HTMLTokenizer` loop + + ## [2.0.4](https://github.com/iabudiab/HTMLKit/releases/tag/2.0.4) Released on 2017.04.2 diff --git a/HTMLKit.podspec b/HTMLKit.podspec index 48d2a6c..4991a29 100644 --- a/HTMLKit.podspec +++ b/HTMLKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "HTMLKit" - s.version = "2.0.4" + s.version = "2.0.5" s.summary = "HTMLKit, an Objective-C framework for your everyday HTML needs." s.license = "MIT" s.homepage = "https://github.com/iabudiab/HTMLKit" diff --git a/Sources/CSSInputStream.m b/Sources/CSSInputStream.m index 4b3cb81..f1fc03b 100644 --- a/Sources/CSSInputStream.m +++ b/Sources/CSSInputStream.m @@ -24,14 +24,14 @@ - (void)consumeWhitespace - (NSString *)consumeIdentifier { - CFMutableStringRef value = CFStringCreateMutable(kCFAllocatorDefault, 0); - if (!isValidIdentifierStart([self inputCharacterPointAtOffset:0], [self inputCharacterPointAtOffset:1], [self inputCharacterPointAtOffset:2])) { return nil; } + CFMutableStringRef value = CFStringCreateMutable(kCFAllocatorDefault, 0); + while (YES) { UTF32Char codePoint = [self consumeNextInputCharacter]; if (codePoint == EOF) { @@ -47,7 +47,12 @@ - (NSString *)consumeIdentifier } } - return (__bridge NSString *)(CFStringGetLength(value) > 0 ? value : nil); + if (CFStringGetLength(value) > 0) { + return (__bridge_transfer NSString *)value; + } + + CFRelease(value); + return nil; } - (NSString *)consumeStringWithEndingCodePoint:(UTF32Char)endingCodePoint @@ -85,7 +90,12 @@ - (NSString *)consumeStringWithEndingCodePoint:(UTF32Char)endingCodePoint } } - return (__bridge NSString *)(CFStringGetLength(value) > 0 ? value : nil); + if (CFStringGetLength(value) > 0) { + return (__bridge_transfer NSString *)value; + } + + CFRelease(value); + return nil; } - (UTF32Char)consumeEscapedCodePoint @@ -105,7 +115,7 @@ - (UTF32Char)consumeEscapedCodePoint [self consumeNextInputCharacter]; } - NSScanner *scanner = [NSScanner scannerWithString:(__bridge NSString *)(hexString)]; + NSScanner *scanner = [NSScanner scannerWithString:(__bridge_transfer NSString *)(hexString)]; unsigned int number; [scanner scanHexInt:&number]; diff --git a/Sources/HTMLCharacterData.m b/Sources/HTMLCharacterData.m index 68a7e19..46615ca 100644 --- a/Sources/HTMLCharacterData.m +++ b/Sources/HTMLCharacterData.m @@ -24,14 +24,25 @@ - (instancetype)initWithName:(NSString *)name type:(HTMLNodeType)type data:(NSSt { self = [super initWithName:name type:type]; if (self) { - _data = [[NSMutableString alloc] initWithString:data ?: @""]; + if (data) { + _data = [[NSMutableString alloc] initWithString:data]; + } } return self; } +- (NSString *)data +{ + if (_data == nil) { + _data = [[NSMutableString alloc] initWithString:@""]; + } + + return _data; +} + - (NSString *)textContent { - return [_data copy]; + return [self.data copy]; } - (void)setTextContent:(NSString *)textContent @@ -41,7 +52,7 @@ - (void)setTextContent:(NSString *)textContent - (NSUInteger)length { - return _data.length; + return self.data.length; } #pragma mark - Data @@ -81,7 +92,7 @@ - (void)replaceDataInRange:(NSRange)range withData:(NSString *)data range.length = MIN(range.length, self.length - range.location); - [_data replaceCharactersInRange:range withString:data]; + [(NSMutableString *)self.data replaceCharactersInRange:range withString:data]; [self.ownerDocument didRemoveCharacterDataInNode:self atOffset:range.location withLength:range.length]; [self.ownerDocument didAddCharacterDataToNode:self atOffset:range.location withLength:data.length]; } diff --git a/Sources/HTMLElement.m b/Sources/HTMLElement.m index ec3ef89..f36bc02 100644 --- a/Sources/HTMLElement.m +++ b/Sources/HTMLElement.m @@ -32,7 +32,7 @@ - (instancetype)init - (instancetype)initWithTagName:(NSString *)tagName { - return [self initWithTagName:tagName attributes:@{}]; + return [self initWithTagName:tagName attributes:nil]; } - (instancetype)initWithTagName:(NSString *)tagName attributes:(NSDictionary *)attributes @@ -45,8 +45,9 @@ - (instancetype)initWithTagName:(NSString *)tagName namespace:(HTMLNamespace)htm self = [super initWithName:tagName type:HTMLNodeElement]; if (self) { _tagName = [tagName copy]; - _attributes = [HTMLOrderedDictionary new]; + _attributes = nil; if (attributes != nil) { + _attributes = [HTMLOrderedDictionary new]; [_attributes addEntriesFromDictionary:attributes]; } _htmlNamespace = htmlNamespace; @@ -56,24 +57,33 @@ - (instancetype)initWithTagName:(NSString *)tagName namespace:(HTMLNamespace)htm #pragma mark - Special Attributes +- (NSMutableDictionary *)attributes +{ + if (_attributes == nil) { + _attributes = [HTMLOrderedDictionary new]; + } + + return _attributes; +} + - (NSString *)elementId { - return _attributes[@"id"] ?: @""; + return self.attributes[@"id"] ?: @""; } - (void)setElementId:(NSString *)elementId { - _attributes[@"id"] = elementId; + self.attributes[@"id"] = elementId; } - (NSString *)className { - return _attributes[@"class"] ?: @""; + return self.attributes[@"class"] ?: @""; } - (void)setClassName:(NSString *)className { - _attributes[@"class"] = className; + self.attributes[@"class"] = className; } - (HTMLDOMTokenList *)classList @@ -85,22 +95,22 @@ - (HTMLDOMTokenList *)classList - (BOOL)hasAttribute:(NSString *)name { - return _attributes[name] != nil; + return self.attributes[name] != nil; } - (NSString *)objectForKeyedSubscript:(NSString *)name; { - return _attributes[name]; + return self.attributes[name]; } - (void)setObject:(NSString *)value forKeyedSubscript:(NSString *)attribute { - _attributes[attribute] = value; + self.attributes[attribute] = value; } - (void)removeAttribute:(NSString *)name { - [_attributes removeObjectForKey:name]; + [self.attributes removeObjectForKey:name]; } - (NSString *)textContent diff --git a/Sources/HTMLKit-Info.plist b/Sources/HTMLKit-Info.plist index a058d41..11b6ce9 100644 --- a/Sources/HTMLKit-Info.plist +++ b/Sources/HTMLKit-Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 2.0.4 + 2.0.5 CFBundleSignature ???? CFBundleVersion diff --git a/Sources/HTMLNode.m b/Sources/HTMLNode.m index e1c74c3..da9d2b6 100644 --- a/Sources/HTMLNode.m +++ b/Sources/HTMLNode.m @@ -36,13 +36,22 @@ - (instancetype)initWithName:(NSString *)name type:(HTMLNodeType)type if (self) { _name = name; _nodeType = type; - _childNodes = [NSMutableOrderedSet new]; + _childNodes = nil; } return self; } #pragma mark - Properties +- (NSOrderedSet *)childNodes +{ + if (_childNodes == nil) { + _childNodes = [NSMutableOrderedSet new]; + } + + return _childNodes; +} + - (HTMLDocument *)ownerDocument { if (_nodeType == HTMLNodeDocument) { @@ -55,7 +64,9 @@ - (HTMLDocument *)ownerDocument - (void)setOwnerDocument:(HTMLDocument *)ownerDocument { _ownerDocument = ownerDocument; - [self.childNodes.array makeObjectsPerformSelector:@selector(setOwnerDocument:) withObject:ownerDocument]; + for (HTMLNode *child in self.childNodes) { + [child setOwnerDocument:ownerDocument]; + } } - (HTMLNode *)rootNode @@ -262,7 +273,9 @@ - (HTMLNode *)insertNode:(HTMLNode *)node beforeChildNode:(HTMLNode *)child [node removeAllChildNodes]; } - [nodes makeObjectsPerformSelector:@selector(setParentNode:) withObject:self]; + for (HTMLNode *node in nodes) { + [node setParentNode:self]; + } return node; } @@ -322,7 +335,7 @@ - (HTMLNode *)removeChildNodeAtIndex:(NSUInteger)index - (void)reparentChildNodesIntoNode:(HTMLNode *)node { - for (HTMLNode *child in self.childNodes.array) { + for (HTMLNode *child in self.childNodes) { [node appendNode:child]; } [(NSMutableOrderedSet *)self.childNodes removeAllObjects]; @@ -330,7 +343,9 @@ - (void)reparentChildNodesIntoNode:(HTMLNode *)node - (void)removeAllChildNodes { - [self.childNodes.array makeObjectsPerformSelector:@selector(setParentNode:) withObject:nil]; + for (HTMLNode *child in self.childNodes) { + [child setParentNode:nil]; + } [(NSMutableOrderedSet *)self.childNodes removeAllObjects]; } diff --git a/Sources/HTMLTokenizer.m b/Sources/HTMLTokenizer.m index 705eb45..9f69ee6 100644 --- a/Sources/HTMLTokenizer.m +++ b/Sources/HTMLTokenizer.m @@ -77,14 +77,16 @@ - (NSString *)string - (id)nextObject { - while (_eof == NO && _tokens.count == 0) { - [self read]; - } - HTMLToken *nextToken = [_tokens firstObject]; - if (_tokens.count > 0) { - [_tokens removeObjectAtIndex:0]; + @autoreleasepool { + while (_eof == NO && _tokens.count == 0) { + [self read]; + } + HTMLToken *nextToken = [_tokens firstObject]; + if (_tokens.count > 0) { + [_tokens removeObjectAtIndex:0]; + } + return nextToken; } - return nextToken; } - (void)read diff --git a/Sources/include/HTMLElement.h b/Sources/include/HTMLElement.h index dcf5372..524921a 100644 --- a/Sources/include/HTMLElement.h +++ b/Sources/include/HTMLElement.h @@ -75,7 +75,7 @@ NS_ASSUME_NONNULL_BEGIN @param attributes The attributes. @return A new HTML element. */ -- (instancetype)initWithTagName:(NSString *)tagName attributes:(NSDictionary *)attributes; +- (instancetype)initWithTagName:(NSString *)tagName attributes:(nullable NSDictionary *)attributes; /** Initializes a new HTML element with the given tag name, namespace, and attributes. @@ -85,7 +85,7 @@ NS_ASSUME_NONNULL_BEGIN @param attributes The attributes. @return A new HTML element. */ -- (instancetype)initWithTagName:(NSString *)tagName namespace:(HTMLNamespace)htmlNamespace attributes:(NSDictionary *)attributes; +- (instancetype)initWithTagName:(NSString *)tagName namespace:(HTMLNamespace)htmlNamespace attributes:(nullable NSDictionary *)attributes; /** Checks whether this element has an attribute with the given name. diff --git a/Sources/include/module.modulemap b/Sources/include/HTMLKit.modulemap similarity index 100% rename from Sources/include/module.modulemap rename to Sources/include/HTMLKit.modulemap