Merge branch '0.9.1'

This commit is contained in:
Alexander Ljungberg committed 2011-04-21 20:02:22 -04:00
commit 321c11ec9f
3 files changed
+154 -66

No files matched your search

+69 -66
View File
@@ -441,71 +441,48 @@ var _CPKeyedUnarchiverDecodeObjectAtIndex = function(self, anIndex)
var object = self._objects[anIndex];
if (object)
{
if (object === self._objects[0])
return nil;
else
return object;
var object,
plistObject = self._plistObjects[anIndex],
plistObjectClass = plistObject.isa;
if (plistObjectClass === CPDictionaryClass || plistObjectClass === CPMutableDictionaryClass)
// Don't return immediately here. The _CPKeyedArchiverValueClass unwrapper code
// hasn't executed yet.
}
else
{
var plistClass = self._plistObjects[plistObject.valueForKey(_CPKeyedArchiverClassKey).valueForKey(_CPKeyedArchiverUIDKey)],
className = plistClass.valueForKey(_CPKeyedArchiverClassNameKey),
classes = plistClass.valueForKey(_CPKeyedArchiverClassesKey),
theClass = [self classForClassName:className];
var plistObject = self._plistObjects[anIndex],
plistObjectClass = plistObject.isa;
if (!theClass)
theClass = CPClassFromString(className);
if (!theClass && (self._delegateSelectors & CPKeyedUnarchiverDelegate_unarchiver_cannotDecodeObjectOfClassName_originalClasses_))
theClass = [_delegate unarchiver:self cannotDecodeObjectOfClassName:className originalClasses:classes];
if (!theClass)
[CPException raise:CPInvalidUnarchiveOperationException reason:@"-[CPKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (" + className + @")"];
var savedPlistObject = self._plistObject;
self._plistObject = plistObject;
// Should we only call this on _CPCibClassSwapper? (currently the only class that makes use of this).
object = [theClass allocWithCoder:self];
// It is important to do this before calling initWithCoder so that decoding can be self referential (something = self).
self._objects[anIndex] = object;
var processedObject = [object initWithCoder:self];
self._plistObject = savedPlistObject;
if (processedObject !== object)
if (plistObjectClass === CPDictionaryClass || plistObjectClass === CPMutableDictionaryClass)
{
if (self._delegateSelectors & _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector)
[self._delegate unarchiver:self willReplaceObject:object withObject:processedObject];
var plistClass = self._plistObjects[plistObject.valueForKey(_CPKeyedArchiverClassKey).valueForKey(_CPKeyedArchiverUIDKey)],
className = plistClass.valueForKey(_CPKeyedArchiverClassNameKey),
classes = plistClass.valueForKey(_CPKeyedArchiverClassesKey),
theClass = [self classForClassName:className];
object = processedObject;
self._objects[anIndex] = processedObject;
}
if (!theClass)
theClass = CPClassFromString(className);
processedObject = [object awakeAfterUsingCoder:self];
if (!theClass && (self._delegateSelectors & CPKeyedUnarchiverDelegate_unarchiver_cannotDecodeObjectOfClassName_originalClasses_))
theClass = [_delegate unarchiver:self cannotDecodeObjectOfClassName:className originalClasses:classes];
if (processedObject !== object)
{
if (self._delegateSelectors & _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector)
[self._delegate unarchiver:self willReplaceObject:object withObject:processedObject];
if (!theClass)
[CPException raise:CPInvalidUnarchiveOperationException reason:@"-[CPKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (" + className + @")"];
object = processedObject;
self._objects[anIndex] = processedObject;
}
var savedPlistObject = self._plistObject;
if (self._delegate)
{
if (self._delegateSelectors & _CPKeyedUnarchiverDidDecodeObjectSelector)
processedObject = [self._delegate unarchiver:self didDecodeObject:object];
self._plistObject = plistObject;
if (processedObject && processedObject != object)
// Should we only call this on _CPCibClassSwapper? (currently the only class that makes use of this).
object = [theClass allocWithCoder:self];
// It is important to do this before calling initWithCoder so that decoding can be self referential (something = self).
self._objects[anIndex] = object;
var processedObject = [object initWithCoder:self];
self._plistObject = savedPlistObject;
if (processedObject !== object)
{
if (self._delegateSelectors & _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector)
[self._delegate unarchiver:self willReplaceObject:object withObject:processedObject];
@@ -513,22 +490,48 @@ var _CPKeyedUnarchiverDecodeObjectAtIndex = function(self, anIndex)
object = processedObject;
self._objects[anIndex] = processedObject;
}
}
}
else
{
self._objects[anIndex] = object = plistObject;
if ([object class] === CPStringClass)
{
if (object === _CPKeyedArchiverNullString)
processedObject = [object awakeAfterUsingCoder:self];
if (processedObject !== object)
{
self._objects[anIndex] = self._objects[0];
if (self._delegateSelectors & _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector)
[self._delegate unarchiver:self willReplaceObject:object withObject:processedObject];
return nil;
object = processedObject;
self._objects[anIndex] = processedObject;
}
if (self._delegate)
{
if (self._delegateSelectors & _CPKeyedUnarchiverDidDecodeObjectSelector)
processedObject = [self._delegate unarchiver:self didDecodeObject:object];
if (processedObject && processedObject != object)
{
if (self._delegateSelectors & _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector)
[self._delegate unarchiver:self willReplaceObject:object withObject:processedObject];
object = processedObject;
self._objects[anIndex] = processedObject;
}
}
}
else
{
self._objects[anIndex] = object = plistObject;
if ([object class] === CPStringClass)
{
if (object === _CPKeyedArchiverNullString)
{
self._objects[anIndex] = self._objects[0];
return nil;
}
else
self._objects[anIndex] = object = plistObject;
}
else
self._objects[anIndex] = object = plistObject;
}
}
+41
View File
@@ -0,0 +1,41 @@
@import <AppKit/CPTextField.j>
[CPApplication sharedApplication]
@implementation CPTextFieldTest : OJTestCase
{
}
/*!
Detect regressions with JS object theme attribute encoding in subclasses.
This test is not actually CPTextField specific at all. This just happens
to be the first place the keyed archiving bug was discovered, and there is
an additional, more specific, test in CPKeyedArchiverTest.
*/
- (void)testArchiveThemeAttributes
{
var view = [[CPTextFieldSubclass alloc] initWithFrame:CGRectMakeZero()],
decoded = [CPKeyedUnarchiver unarchiveObjectWithData:[CPKeyedArchiver archivedDataWithRootObject:view]];
[self assert:[view valueForThemeAttribute:@"content-inset"].top equals:2 message:@"content-inset should initialise correctly"];
[self assert:[view valueForThemeAttribute:@"content-inset"].top equals:[decoded valueForThemeAttribute:@"content-inset"].top message:@"content-inset should unarchive correctly"];
}
@end
@implementation CPTextFieldSubclass : CPTextField
{
}
- (id)initWithFrame:aFrame
{
if (self = [super initWithFrame:aFrame])
{
[self setValue:CGInsetMake(2.0, 2.0, 2.0, 2.0) forThemeAttribute:"content-inset"];
}
return self;
}
@end
+44
View File
@@ -0,0 +1,44 @@
@import <Foundation/CPKeyedArchiver.j>
@import <Foundation/CPKeyedUnarchiver.j>
@implementation CPKeyedArchiverTest : OJTestCase
{
}
- (void)testJavaScriptObject
{
var original = [Archivable new];
[original setAJsObject:{ 'top': 5 }];
var decoded = [CPKeyedUnarchiver unarchiveObjectWithData:[CPKeyedArchiver archivedDataWithRootObject:original]]
[self assert:5 equals:[decoded aJsObject].top message:"JS object encoded and decoded right"];
}
@end
@implementation Archivable : CPObject
{
JSObject aJsObject @accessors;
}
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super init])
{
// Note we decode this twice to expose a bug where the cached decoded
// values did not properly unwrap JS objects.
aJsObject = [aCoder decodeObjectForKey:@"aJsObject"];
aJsObject = [aCoder decodeObjectForKey:@"aJsObject"];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:aJsObject forKey:@"aJsObject"];
}
@end