Skip to content

Add framework target #97

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Sep 26, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[submodule "src/tests/vendor/mustache/spec"]
path = src/tests/vendor/mustache/spec
url = https://github.com/mustache/spec.git
[submodule "src/vendor/groue/jrswizzle"]
path = src/vendor/groue/jrswizzle
url = https://github.com/groue/jrswizzle.git
387 changes: 327 additions & 60 deletions src/GRMustache.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "6586A05C1B9E2D720067C98E"
BuildableName = "GRMustache.framework"
BlueprintName = "GRMustache"
ReferencedContainer = "container:GRMustache.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "6586A05C1B9E2D720067C98E"
BuildableName = "GRMustache.framework"
BlueprintName = "GRMustache"
ReferencedContainer = "container:GRMustache.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "6586A05C1B9E2D720067C98E"
BuildableName = "GRMustache.framework"
BlueprintName = "GRMustache"
ReferencedContainer = "container:GRMustache.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
26 changes: 26 additions & 0 deletions src/GRMustache/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>8.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
56 changes: 0 additions & 56 deletions src/classes/GRMustache.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,62 +59,6 @@ typedef struct {
+ (GRMustacheVersion)libraryVersion AVAILABLE_GRMUSTACHE_VERSION_7_0_AND_LATER;


////////////////////////////////////////////////////////////////////////////////
/// @name Preventing NSUndefinedKeyException in Development configuration
////////////////////////////////////////////////////////////////////////////////

/**
* Have GRMustache avoid most `NSUndefinedKeyExceptions` when rendering
* templates.
*
* The rendering of a GRMustache template can lead to `NSUndefinedKeyExceptions`
* to be raised, because of the usage of the `valueForKey:` method. Those
* exceptions are nicely handled by GRMustache, and are part of the regular
* rendering of a template.
*
* Unfortunately, Objective-C exceptions have several drawbacks, particularly:
*
* 1. they play badly with autorelease pools, and are reputed to leak memory.
* 2. they usually stop your debugger when you are developping your application.
*
* The first point is indeed a matter of worry: Apple does not guarantee that
* exceptions raised by `valueForKey:` do not leak memory. However, I never had
* any evidence of such a leak from NSObject's implementation.
*
* Should you still worry, we recommend that you avoid the `valueForKey:` method
* altogether. Instead, implement the [keyed subscripting](http://clang.llvm.org/docs/ObjectiveCLiterals.html#dictionary-style-subscripting)
* `objectForKeyedSubscript:` method on objects that you provide to GRMustache.
*
* The second point is valid also: NSUndefinedKeyException raised by template
* rendering may become a real annoyance when you are debugging your project,
* because it's likely you've told your debugger to stop on every Objective-C
* exceptions.
*
* You can avoid them as well: make sure you invoke once, early in your
* application, the `preventNSUndefinedKeyExceptionAttack` method.
*
* Depending on the number of NSUndefinedKeyException that get prevented, you
* will experience a slight performance hit, or a performance improvement.
*
* Since the main use case for this method is to avoid Xcode breaks on rendering
* exceptions, the best practice is to conditionally invoke this method, using
* the [NS_BLOCK_ASSERTIONS](http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html)
* that helps identifying the Debug configuration of your targets:
*
* ```
* #if !defined(NS_BLOCK_ASSERTIONS)
* // Debug configuration: keep GRMustache quiet
* [GRMustache preventNSUndefinedKeyExceptionAttack];
* #endif
* ```
*
* **Companion guide:** https://github.com/groue/GRMustache/blob/master/Guides/runtime.md
*
* @since v1.7
*/
+ (void)preventNSUndefinedKeyExceptionAttack AVAILABLE_GRMUSTACHE_VERSION_7_0_AND_LATER;


////////////////////////////////////////////////////////////////////////////////
/// @name Standard Library
////////////////////////////////////////////////////////////////////////////////
Expand Down
6 changes: 0 additions & 6 deletions src/classes/GRMustache.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
#import "GRMustacheEachFilter_private.h"
#import "GRMustacheLocalizer.h"


// =============================================================================
#pragma mark - GRMustache

Expand All @@ -40,11 +39,6 @@ @implementation GRMustache
// =============================================================================
#pragma mark - Global services

+ (void)preventNSUndefinedKeyExceptionAttack
{
[GRMustacheKeyAccess preventNSUndefinedKeyExceptionAttack];
}

+ (GRMustacheVersion)libraryVersion
{
return (GRMustacheVersion){
Expand Down
3 changes: 0 additions & 3 deletions src/classes/GRMustache_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ typedef struct {
// Documented in GRMustache.h
+ (GRMustacheVersion)libraryVersion GRMUSTACHE_API_PUBLIC;

// Documented in GRMustache.h
+ (void)preventNSUndefinedKeyExceptionAttack GRMUSTACHE_API_PUBLIC;

// Documented in GRMustache.h
+ (NSObject *)standardLibrary GRMUSTACHE_API_PUBLIC;

Expand Down
104 changes: 0 additions & 104 deletions src/classes/Rendering/GRMustacheKeyAccess.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
#import <pthread.h>
#import "GRMustacheKeyAccess_private.h"
#import "GRMustacheSafeKeyAccess.h"
#import "JRSwizzle.h"


#if !defined(NS_BLOCK_ASSERTIONS)
// For testing purpose
Expand Down Expand Up @@ -144,13 +142,6 @@ + (id)valueForMustacheKey:(NSString *)key inObject:(id)object unsafeKeyAccess:(B

@try {

// valueForKey: may throw NSUndefinedKeyException, and user may want to
// prevent them.

if (preventsNSUndefinedKeyException) {
[GRMustacheKeyAccess startPreventingNSUndefinedKeyExceptionFromObject:object];
}

// We don't want to use NSArray, NSSet and NSOrderedSet implementation
// of valueForKey:, because they return another collection: see issue
// #21 and "anchored key should not extract properties inside an array"
Expand All @@ -172,18 +163,6 @@ + (id)valueForMustacheKey:(NSString *)key inObject:(id)object unsafeKeyAccess:(B
if (![[exception name] isEqualToString:NSUndefinedKeyException]) {
[exception raise];
}
#if !defined(NS_BLOCK_ASSERTIONS)
else {
// For testing purpose
GRMustacheKeyAccessDidCatchNSUndefinedKeyException = YES;
}
#endif
}

@finally {
if (preventsNSUndefinedKeyException) {
[GRMustacheKeyAccess stopPreventingNSUndefinedKeyExceptionFromObject:object];
}
}

return nil;
Expand Down Expand Up @@ -504,91 +483,8 @@ + (NSMutableSet *)propertyGettersForClass:(Class)klass
return safeKeys;
}


// =============================================================================
#pragma mark - NSUndefinedKeyException prevention

static BOOL preventsNSUndefinedKeyException = NO;

static pthread_key_t GRPreventedObjectsStorageKey;
void freePreventedObjectsStorage(void *objects) {
[(NSMutableSet *)objects release];
}
#define setupPreventedObjectsStorage() pthread_key_create(&GRPreventedObjectsStorageKey, freePreventedObjectsStorage)
#define getCurrentThreadPreventedObjects() (NSMutableSet *)pthread_getspecific(GRPreventedObjectsStorageKey)
#define setCurrentThreadPreventedObjects(objects) pthread_setspecific(GRPreventedObjectsStorageKey, objects)

+ (void)preventNSUndefinedKeyExceptionAttack
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self setupNSUndefinedKeyExceptionPrevention];
});
}

+ (void)setupNSUndefinedKeyExceptionPrevention
{
preventsNSUndefinedKeyException = YES;

// Swizzle [NSObject valueForUndefinedKey:]

[NSObject jr_swizzleMethod:@selector(valueForUndefinedKey:)
withMethod:@selector(GRMustacheKeyAccessValueForUndefinedKey_NSObject:)
error:nil];


// Swizzle [NSManagedObject valueForUndefinedKey:]

if (NSManagedObjectClass) {
[NSManagedObjectClass jr_swizzleMethod:@selector(valueForUndefinedKey:)
withMethod:@selector(GRMustacheKeyAccessValueForUndefinedKey_NSManagedObject:)
error:nil];
}

setupPreventedObjectsStorage();
}

+ (void)startPreventingNSUndefinedKeyExceptionFromObject:(id)object
{
NSMutableSet *objects = getCurrentThreadPreventedObjects();
if (objects == NULL) {
objects = [[NSMutableSet alloc] init];
setCurrentThreadPreventedObjects(objects);
}

[objects addObject:object];
}

+ (void)stopPreventingNSUndefinedKeyExceptionFromObject:(id)object
{
[getCurrentThreadPreventedObjects() removeObject:object];
}

@end

@implementation NSObject(GRMustacheKeyAccessPreventionOfNSUndefinedKeyException)

// NSObject
- (id)GRMustacheKeyAccessValueForUndefinedKey_NSObject:(NSString *)key
{
if ([getCurrentThreadPreventedObjects() containsObject:self]) {
return nil;
}
return [self GRMustacheKeyAccessValueForUndefinedKey_NSObject:key];
}

// NSManagedObject
- (id)GRMustacheKeyAccessValueForUndefinedKey_NSManagedObject:(NSString *)key
{
if ([getCurrentThreadPreventedObjects() containsObject:self]) {
return nil;
}
return [self GRMustacheKeyAccessValueForUndefinedKey_NSManagedObject:key];
}

@end


// =============================================================================
#pragma mark - Foundation implementations

Expand Down
15 changes: 0 additions & 15 deletions src/classes/Rendering/GRMustacheKeyAccess_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,11 @@
#import <Foundation/Foundation.h>
#import "GRMustacheAvailabilityMacros_private.h"

#if !defined(NS_BLOCK_ASSERTIONS)
/**
* This global variable is used by GRPreventNSUndefinedKeyExceptionAttackTest.
*/
extern BOOL GRMustacheKeyAccessDidCatchNSUndefinedKeyException;
#endif

/**
* GRMustacheKeyAccess implements all the GRMustache key-fetching logic.
*/
@interface GRMustacheKeyAccess : NSObject

/**
* Avoids most NSUndefinedException to be raised by the invocation of
* `valueForMustacheKey:inObject:`.
*
* @see valueForMustacheKey:inObject:
*/
+ (void)preventNSUndefinedKeyExceptionAttack GRMUSTACHE_API_INTERNAL;

/**
* Sends the `objectForKeyedSubscript:` or `valueForKey:` message to object
* with the provided key, and returns the result.
Expand Down
6 changes: 0 additions & 6 deletions src/classes/Shared/GRMustacheAvailabilityMacros.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,3 @@
#else
#define DEPRECATED_IN_GRMUSTACHE_VERSION_7_3_AND_LATER
#endif






Loading