mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-10-09 02:11:00 +00:00
Merge branch '0.9.1'
This commit is contained in:
commit
321c11ec9f
3 files changed
+154
-66
No files matched your search
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in new issue
Block a user