From a09878dcb4f8f8063ab36f9a9f70ca8e24f295fe Mon Sep 17 00:00:00 2001 From: Derek Hammer Date: Mon, 6 Sep 2010 12:07:50 -0500 Subject: [PATCH 1/7] Adding self checks in toll free bridged objects so that they are subclassable. --- Foundation/CPArray.j | 1 + Foundation/CPDictionary.j | 1 + Foundation/CPException.j | 1 + Foundation/CPNumber.j | 1 + Foundation/CPString.j | 1 + Tests/Foundation/SubclassTollFreeTest.j | 59 +++++++++++++++++++++++++ 6 files changed, 64 insertions(+) create mode 100644 Tests/Foundation/SubclassTollFreeTest.j diff --git a/Foundation/CPArray.j b/Foundation/CPArray.j index 6ee14b6af..f6b6566de 100755 --- a/Foundation/CPArray.j +++ b/Foundation/CPArray.j @@ -108,6 +108,7 @@ CPEnumerationReverse = 1 << 1; */ + (id)alloc { + if ([self class] !== CPArray && [self class] !== CPMutableArray) return [super alloc]; return []; } diff --git a/Foundation/CPDictionary.j b/Foundation/CPDictionary.j index acb4cca1e..c352c1afa 100755 --- a/Foundation/CPDictionary.j +++ b/Foundation/CPDictionary.j @@ -84,6 +84,7 @@ */ + (id)alloc { + if ([self class] !== CPDictionary && [self class] !== CPMutableDictionary) return [super alloc]; return new CFMutableDictionary(); } diff --git a/Foundation/CPException.j b/Foundation/CPException.j index 770c6ad63..7a9c8c959 100755 --- a/Foundation/CPException.j +++ b/Foundation/CPException.j @@ -54,6 +54,7 @@ if (input == nil) */ + (id)alloc { + if ([self class] !== CPException) return [super alloc]; return new Error(); } diff --git a/Foundation/CPNumber.j b/Foundation/CPNumber.j index a0bbef39e..e6efff8fb 100644 --- a/Foundation/CPNumber.j +++ b/Foundation/CPNumber.j @@ -43,6 +43,7 @@ var __placeholder = new Number(), + (id)alloc { + if ([self class] !== CPNumber) return [super alloc]; return __placeholder; } diff --git a/Foundation/CPString.j b/Foundation/CPString.j index cb5b23917..87831a567 100644 --- a/Foundation/CPString.j +++ b/Foundation/CPString.j @@ -91,6 +91,7 @@ var CPStringRegexSpecialCharacters = [ */ + (id)alloc { + if ([self class] !== CPString) return [super alloc]; return new String; } diff --git a/Tests/Foundation/SubclassTollFreeTest.j b/Tests/Foundation/SubclassTollFreeTest.j new file mode 100644 index 000000000..effa6835f --- /dev/null +++ b/Tests/Foundation/SubclassTollFreeTest.j @@ -0,0 +1,59 @@ +@implementation SubclassTollFreeTest : OJTestCase + +- (void)testThatSubclassTollFreeDoesAllowForSubclassing +{ + [OJAssert assert:@"a" equals:[[[MyDict alloc] init] newMessage]]; + [OJAssert assert:@"a" equals:[[[MyString alloc] init] newMessage]]; + [OJAssert assert:@"a" equals:[[[MyNum alloc] init] newMessage]]; + [OJAssert assert:@"a" equals:[[[MyException alloc] init] newMessage]]; + [OJAssert assert:@"a" equals:[[[MyArray alloc] init] newMessage]]; +} + +@end + +@import + +@implementation MyDict : CPDictionary + +- (id)newMessage +{ + return "a"; +} + +@end + +@implementation MyNum : CPNumber + +- (id)newMessage +{ + return "a"; +} + +@end + +@implementation MyString : CPString + +- (id)newMessage +{ + return "a"; +} + +@end + +@implementation MyException : CPException + +- (id)newMessage +{ + return "a"; +} + +@end + +@implementation MyArray : CPArray + +- (id)newMessage +{ + return "a"; +} + +@end From 8e5471d0fe90ac21d4cb71b496c990149f5be598 Mon Sep 17 00:00:00 2001 From: Derek Hammer Date: Mon, 6 Sep 2010 13:45:46 -0500 Subject: [PATCH 2/7] Updating CPData and CPDate to be subclassable. Only non-subclassable toll free bridged object is CPURL at this point. --- Foundation/CPData.j | 1 + Foundation/CPDate.j | 1 + Tests/Foundation/SubclassTollFreeTest.j | 58 +++++++++++++++++++++++-- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/Foundation/CPData.j b/Foundation/CPData.j index 0a75abd36..bb03fd0d7 100644 --- a/Foundation/CPData.j +++ b/Foundation/CPData.j @@ -36,6 +36,7 @@ + (id)alloc { + if ([self class] !== CPData) return [super alloc]; return new CFMutableData(); } diff --git a/Foundation/CPDate.j b/Foundation/CPDate.j index 3ecdd21a4..92a7e4a28 100644 --- a/Foundation/CPDate.j +++ b/Foundation/CPDate.j @@ -39,6 +39,7 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 1, 1, 0, 0, 0, 0)); + (id)alloc { + if ([self class] !== CPDate) return [super alloc]; return new Date; } diff --git a/Tests/Foundation/SubclassTollFreeTest.j b/Tests/Foundation/SubclassTollFreeTest.j index effa6835f..817d4c8ca 100644 --- a/Tests/Foundation/SubclassTollFreeTest.j +++ b/Tests/Foundation/SubclassTollFreeTest.j @@ -1,14 +1,48 @@ @implementation SubclassTollFreeTest : OJTestCase -- (void)testThatSubclassTollFreeDoesAllowForSubclassing +- (void)testThatSubclassTollFreeDoesAllowForSubclassingDictionary +{ + var target = [[MyDict alloc] init]; + [OJAssert assert:@"a" equals:[target newMessage]]; + [OJAssert assert:0 equals:[target count]]; +} + +- (void)testThatSubclassTollFreeDoesAllowForSubclassingString +{ + var target = [[MyString alloc] initWithString:@"adsf"]; + [OJAssert assert:@"a" equals:[target newMessage]]; + [OJAssert assert:4 equals:[target length]]; + + var target2 = "agdsa"; + [OJAssert assertThrows:function(){ [target2 newMessage]; }]; + [OJAssert assert:5 equals:[target2 length]]; +} + +- (void)testThatSubclassTollFreeDoesAllowForSubclassingNumber { - [OJAssert assert:@"a" equals:[[[MyDict alloc] init] newMessage]]; - [OJAssert assert:@"a" equals:[[[MyString alloc] init] newMessage]]; [OJAssert assert:@"a" equals:[[[MyNum alloc] init] newMessage]]; +} + +- (void)testThatSubclassTollFreeDoesAllowForSubclassingException +{ [OJAssert assert:@"a" equals:[[[MyException alloc] init] newMessage]]; +} + +- (void)testThatSubclassTollFreeDoesAllowForSubclassingArray +{ [OJAssert assert:@"a" equals:[[[MyArray alloc] init] newMessage]]; } +- (void)testThatSubclassTollFreeDoesAllowForSubclassingDate +{ + [OJAssert assert:@"a" equals:[[[MyDate alloc] init] newMessage]]; +} + +- (void)testThatSubclassTollFreeDoesAllowForSubclassingData +{ + [OJAssert assert:@"a" equals:[[[MyData alloc] init] newMessage]]; +} + @end @import @@ -57,3 +91,21 @@ } @end + +@implementation MyDate : CPDate + +- (id)newMessage +{ + return "a"; +} + +@end + +@implementation MyData : CPData + +- (id)newMessage +{ + return "a"; +} + +@end From 4e1766485ff7136f5c550be253c4ef9f521b9cb5 Mon Sep 17 00:00:00 2001 From: Derek Hammer Date: Mon, 6 Sep 2010 13:46:27 -0500 Subject: [PATCH 3/7] Updating CPDictionary and CPString to both actually subclass.. not just create a new object without inherited properties. --- Foundation/CPDictionary.j | 5 +++-- Foundation/CPString.j | 13 ++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Foundation/CPDictionary.j b/Foundation/CPDictionary.j index c352c1afa..a628db87f 100755 --- a/Foundation/CPDictionary.j +++ b/Foundation/CPDictionary.j @@ -84,8 +84,9 @@ */ + (id)alloc { - if ([self class] !== CPDictionary && [self class] !== CPMutableDictionary) return [super alloc]; - return new CFMutableDictionary(); + var result = new CFMutableDictionary(); + if ([self class] !== CPDictionary && [self class] !== CPMutableDictionary) result.isa = [self class]; + return result; } /*! diff --git a/Foundation/CPString.j b/Foundation/CPString.j index 87831a567..82570d1a4 100644 --- a/Foundation/CPString.j +++ b/Foundation/CPString.j @@ -135,7 +135,7 @@ var CPStringRegexSpecialCharacters = [ */ - (id)initWithString:(CPString)aString { - return String(aString); + return CreateSubclassableString(aString, [self class]); } /*! @@ -796,6 +796,17 @@ var CPStringRegexSpecialCharacters = [ @end +var CreateSubclassableString = function(aString, aClass) +{ + if (aClass === CPString) return String(aString); + + var result = new String(aString); + + result.isa = aClass; + + return result; +}; + var diacritics = [[192,198],[224,230],[231,231],[232,235],[236,239],[242,246],[249,252]]; // Basic Latin ; Latin-1 Supplement. var normalized = [65,97,99,101,105,111,117]; From f85ab24993ce1a0c14b501adb49171a6c1c77e96 Mon Sep 17 00:00:00 2001 From: Derek Hammer Date: Mon, 6 Sep 2010 14:02:52 -0500 Subject: [PATCH 4/7] Finishing the rest to make them inherit properties of superclasses. --- Foundation/CPArray.j | 5 +++-- Foundation/CPData.j | 5 +++-- Foundation/CPDate.j | 5 +++-- Foundation/CPDictionary.j | 2 +- Foundation/CPNumber.j | 5 +++-- Tests/Foundation/SubclassTollFreeTest.j | 25 ++++++++++++++++++++----- 6 files changed, 33 insertions(+), 14 deletions(-) diff --git a/Foundation/CPArray.j b/Foundation/CPArray.j index f6b6566de..597d7074e 100755 --- a/Foundation/CPArray.j +++ b/Foundation/CPArray.j @@ -108,8 +108,9 @@ CPEnumerationReverse = 1 << 1; */ + (id)alloc { - if ([self class] !== CPArray && [self class] !== CPMutableArray) return [super alloc]; - return []; + var result = []; + result.isa = [self class]; + return result; } /*! diff --git a/Foundation/CPData.j b/Foundation/CPData.j index bb03fd0d7..8e8c20340 100644 --- a/Foundation/CPData.j +++ b/Foundation/CPData.j @@ -36,8 +36,9 @@ + (id)alloc { - if ([self class] !== CPData) return [super alloc]; - return new CFMutableData(); + result = new CFMutableData(); + result.isa = [self class]; + return result; } + (CPData)data diff --git a/Foundation/CPDate.j b/Foundation/CPDate.j index 92a7e4a28..f04b3849b 100644 --- a/Foundation/CPDate.j +++ b/Foundation/CPDate.j @@ -39,8 +39,9 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 1, 1, 0, 0, 0, 0)); + (id)alloc { - if ([self class] !== CPDate) return [super alloc]; - return new Date; + var result = new Date; + result.isa = [self class]; + return result; } + (id)date diff --git a/Foundation/CPDictionary.j b/Foundation/CPDictionary.j index a628db87f..978f6a4dc 100755 --- a/Foundation/CPDictionary.j +++ b/Foundation/CPDictionary.j @@ -85,7 +85,7 @@ + (id)alloc { var result = new CFMutableDictionary(); - if ([self class] !== CPDictionary && [self class] !== CPMutableDictionary) result.isa = [self class]; + result.isa = [self class]; return result; } diff --git a/Foundation/CPNumber.j b/Foundation/CPNumber.j index e6efff8fb..a65949a88 100644 --- a/Foundation/CPNumber.j +++ b/Foundation/CPNumber.j @@ -43,8 +43,9 @@ var __placeholder = new Number(), + (id)alloc { - if ([self class] !== CPNumber) return [super alloc]; - return __placeholder; + var result = new Number(); + result.isa = [self class]; + return result; } + (id)numberWithBool:(BOOL)aBoolean diff --git a/Tests/Foundation/SubclassTollFreeTest.j b/Tests/Foundation/SubclassTollFreeTest.j index 817d4c8ca..b5350ae6a 100644 --- a/Tests/Foundation/SubclassTollFreeTest.j +++ b/Tests/Foundation/SubclassTollFreeTest.j @@ -1,3 +1,8 @@ +@import "../../Foundation/CPNumber.j" +@import "../../Foundation/CPArray.j" +@import "../../Foundation/CPDate.j" +@import "../../Foundation/CPData.j" + @implementation SubclassTollFreeTest : OJTestCase - (void)testThatSubclassTollFreeDoesAllowForSubclassingDictionary @@ -20,27 +25,37 @@ - (void)testThatSubclassTollFreeDoesAllowForSubclassingNumber { - [OJAssert assert:@"a" equals:[[[MyNum alloc] init] newMessage]]; + var target = [[MyNum alloc] init]; + [OJAssert assert:@"a" equals:[target newMessage]]; + [OJAssert assertFalse:[target isEqualToNumber:5]]; } - (void)testThatSubclassTollFreeDoesAllowForSubclassingException { - [OJAssert assert:@"a" equals:[[[MyException alloc] init] newMessage]]; + var target = [[MyException alloc] init]; + [OJAssert assert:@"a" equals:[target newMessage]]; + // there are no internal properties to test here.. so no need to jimmyrig it. } - (void)testThatSubclassTollFreeDoesAllowForSubclassingArray { - [OJAssert assert:@"a" equals:[[[MyArray alloc] init] newMessage]]; + var target = [[MyArray alloc] initWithObjects:@"a"]; + [OJAssert assert:@"a" equals:[target newMessage]]; + [OJAssert assert:1 equals:[target count]]; } - (void)testThatSubclassTollFreeDoesAllowForSubclassingDate { - [OJAssert assert:@"a" equals:[[[MyDate alloc] init] newMessage]]; + var target = [[MyDate alloc] init]; + [OJAssert assert:@"a" equals:[target newMessage]]; + [OJAssert assertTrue:[target timeIntervalSince1970] > 0]; } - (void)testThatSubclassTollFreeDoesAllowForSubclassingData { - [OJAssert assert:@"a" equals:[[[MyData alloc] init] newMessage]]; + var target = [[MyData alloc] initWithRawString:@"b"]; + [OJAssert assert:@"a" equals:[target newMessage]]; + [OJAssert assert:@"b" equals:[target rawString]]; } @end From fc545ed995e1e123cbc20aacc704871556a20234 Mon Sep 17 00:00:00 2001 From: Derek Hammer Date: Mon, 6 Sep 2010 14:18:53 -0500 Subject: [PATCH 5/7] Adding support for CPURL --- Foundation/CPURL.j | 8 ++++++-- Tests/Foundation/SubclassTollFreeTest.j | 22 +++++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/Foundation/CPURL.j b/Foundation/CPURL.j index 1486baad3..a79e1aae4 100644 --- a/Foundation/CPURL.j +++ b/Foundation/CPURL.j @@ -54,7 +54,9 @@ CPURLCustomIconKey = @"CPURLCustomIconKey"; + (id)alloc { - return new CFURL(); + var result = new CFURL(); + result.isa = [self class]; + return result; } - (id)init @@ -81,7 +83,9 @@ CPURLCustomIconKey = @"CPURLCustomIconKey"; - (id)initWithString:(CPString)URLString relativeToURL:(CPURL)aBaseURL { - return new CFURL(URLString, aBaseURL); + var result = new CFURL(URLString, aBaseURL); + result.isa = [self class]; + return result; } + (id)URLWithString:(CPString)URLString relativeToURL:(CPURL)aBaseURL diff --git a/Tests/Foundation/SubclassTollFreeTest.j b/Tests/Foundation/SubclassTollFreeTest.j index b5350ae6a..f7b6191b5 100644 --- a/Tests/Foundation/SubclassTollFreeTest.j +++ b/Tests/Foundation/SubclassTollFreeTest.j @@ -1,8 +1,3 @@ -@import "../../Foundation/CPNumber.j" -@import "../../Foundation/CPArray.j" -@import "../../Foundation/CPDate.j" -@import "../../Foundation/CPData.j" - @implementation SubclassTollFreeTest : OJTestCase - (void)testThatSubclassTollFreeDoesAllowForSubclassingDictionary @@ -58,6 +53,14 @@ [OJAssert assert:@"b" equals:[target rawString]]; } +- (void)testThatSubclassTollFreeDoesAllowForSubclassingURL +{ + var target = [[MyURL alloc] initWithString:@"http://www.google.com"]; + [OJAssert assert:@"a" equals:[target newMessage]]; + [OJAssert assert:@"http://www.google.com" equals:[target absoluteString]]; +} + + @end @import @@ -124,3 +127,12 @@ } @end + +@implementation MyURL : CPURL + +- (id)newMessage +{ + return "a"; +} + +@end From ae5d56471fd51f3b3bd29bb0addac8409d784e8f Mon Sep 17 00:00:00 2001 From: Derek Hammer Date: Thu, 14 Oct 2010 19:31:04 -0500 Subject: [PATCH 6/7] Inlining function, fixing a style issue. --- Foundation/CPString.j | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/Foundation/CPString.j b/Foundation/CPString.j index 82570d1a4..88567a272 100644 --- a/Foundation/CPString.j +++ b/Foundation/CPString.j @@ -135,7 +135,14 @@ var CPStringRegexSpecialCharacters = [ */ - (id)initWithString:(CPString)aString { - return CreateSubclassableString(aString, [self class]); + if (aClass === CPString) + return String(aString); + + var result = new String(aString); + + result.isa = [self class]; + + return result; } /*! @@ -796,17 +803,6 @@ var CPStringRegexSpecialCharacters = [ @end -var CreateSubclassableString = function(aString, aClass) -{ - if (aClass === CPString) return String(aString); - - var result = new String(aString); - - result.isa = aClass; - - return result; -}; - var diacritics = [[192,198],[224,230],[231,231],[232,235],[236,239],[242,246],[249,252]]; // Basic Latin ; Latin-1 Supplement. var normalized = [65,97,99,101,105,111,117]; From d4d831b9ac36a9f6a8d2456d27167c4e61a3e7b6 Mon Sep 17 00:00:00 2001 From: Derek Hammer Date: Wed, 1 Dec 2010 20:12:12 -0800 Subject: [PATCH 7/7] Fixing a bug caused by the function inline. --- Foundation/CPString.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Foundation/CPString.j b/Foundation/CPString.j index 88567a272..d3c62eb3a 100644 --- a/Foundation/CPString.j +++ b/Foundation/CPString.j @@ -135,7 +135,7 @@ var CPStringRegexSpecialCharacters = [ */ - (id)initWithString:(CPString)aString { - if (aClass === CPString) + if ([self class] === CPString) return String(aString); var result = new String(aString);