diff --git a/JSPatch/JPEngine.m b/JSPatch/JPEngine.m index cff9b7b0..8fcb5aab 100644 --- a/JSPatch/JPEngine.m +++ b/JSPatch/JPEngine.m @@ -419,25 +419,14 @@ static void addMethodToProtocol(Protocol* protocol, NSString *selectorName, NSSt static NSDictionary *defineClass(NSString *classDeclaration, JSValue *instanceMethods, JSValue *classMethods) { - NSString *className; - NSString *superClassName; - NSString *protocolNames; - NSScanner *scanner = [NSScanner scannerWithString:classDeclaration]; - [scanner scanUpToString:@":" intoString:&className]; - if (!scanner.isAtEnd) { - scanner.scanLocation = scanner.scanLocation + 1; - [scanner scanUpToString:@"<" intoString:&superClassName]; - if (!scanner.isAtEnd) { - scanner.scanLocation = scanner.scanLocation + 1; - [scanner scanUpToString:@">" intoString:&protocolNames]; - } - } - NSArray *protocols = [protocolNames componentsSeparatedByString:@","]; + NSDictionary *declarationDic = convertJPDeclarationString(classDeclaration); - if (!superClassName) superClassName = @"NSObject"; - className = trim(className); - superClassName = trim(superClassName); + NSString *className = [declarationDic objectForKey:@"className"]; + NSString *superClassName = [declarationDic objectForKey:@"superClassName"]; + NSString *protocolNames = [declarationDic objectForKey:@"protocolNames"]; + + NSArray *protocols = [protocolNames componentsSeparatedByString:@","]; Class cls = NSClassFromString(className); if (!cls) { @@ -845,6 +834,8 @@ static void overrideMethod(Class cls, NSString *selectorName, JSValue *function, static id callSelector(NSString *className, NSString *selectorName, JSValue *arguments, JSValue *instance, BOOL isSuper) { + NSString *clsDeclaration = [[instance valueForProperty:@"__clsDeclaration"] toString]; + if (instance) { instance = formatJSToOC(instance); if (!instance || instance == _nilObj) return @{@"__isNil": @(YES)}; @@ -864,7 +855,18 @@ static id callSelector(NSString *className, NSString *selectorName, JSValue *arg NSString *superSelectorName = [NSString stringWithFormat:@"SUPER_%@", selectorName]; SEL superSelector = NSSelectorFromString(superSelectorName); - Class superCls = [cls superclass]; + Class superCls; + if (clsDeclaration && clsDeclaration.length > 0) { + NSDictionary * declarationDic =convertJPDeclarationString(clsDeclaration); + NSString *defineClsName = [declarationDic objectForKey:@"className"]; + + Class defineClass = NSClassFromString(defineClsName); + superCls = defineClass?[defineClass superclass]:[cls superclass]; + }else + { + superCls = [cls superclass]; + } + Method superMethod = class_getInstanceMethod(superCls, selector); IMP superIMP = method_getImplementation(superMethod); @@ -1337,6 +1339,40 @@ static BOOL blockTypeIsObject(NSString *typeString) return [selectorName stringByReplacingOccurrencesOfString:@"-" withString:@"_"]; } +static NSDictionary *convertJPDeclarationString(NSString *declaration){ + + NSScanner *scanner = [NSScanner scannerWithString:declaration]; + + NSString *className; + NSString *superClassName; + NSString *protocolNames; + [scanner scanUpToString:@":" intoString:&className]; + if (!scanner.isAtEnd) { + scanner.scanLocation = scanner.scanLocation + 1; + [scanner scanUpToString:@"<" intoString:&superClassName]; + if (!scanner.isAtEnd) { + scanner.scanLocation = scanner.scanLocation + 1; + [scanner scanUpToString:@">" intoString:&protocolNames]; + } + } + + if (!superClassName) superClassName = @"NSObject"; + className = trim(className); + superClassName = trim(superClassName); + + NSMutableDictionary *retDic = [[NSMutableDictionary alloc]init]; + if (className) { + [retDic setObject:className forKey:@"className"]; + } + if (superClassName) { + [retDic setObject:superClassName forKey:@"superClassName"]; + } + if (protocolNames) { + [retDic setObject:protocolNames forKey:@"protocolNames"]; + } + return retDic; +} + #pragma mark - Object format diff --git a/JSPatch/JSPatch.js b/JSPatch/JSPatch.js index ee2a6937..4a253c73 100644 --- a/JSPatch/JSPatch.js +++ b/JSPatch/JSPatch.js @@ -115,7 +115,7 @@ var global = this return lastRequire } - var _formatDefineMethods = function(methods, newMethods) { + var _formatDefineMethods = function(methods, newMethods, declaration) { for (var methodName in methods) { (function(){ var originMethod = methods[methodName] @@ -125,6 +125,9 @@ var global = this var ret; try { global.self = args[0] + if (global.self.__obj) { + global.self.__obj.__clsDeclaration = declaration + } args.splice(0,1) ret = originMethod.apply(originMethod, args) global.self = lastSelf @@ -139,8 +142,8 @@ var global = this global.defineClass = function(declaration, instMethods, clsMethods) { var newInstMethods = {}, newClsMethods = {} - _formatDefineMethods(instMethods, newInstMethods) - _formatDefineMethods(clsMethods, newClsMethods) + _formatDefineMethods(instMethods, newInstMethods,declaration) + _formatDefineMethods(clsMethods, newClsMethods,declaration) var ret = _OC_defineClass(declaration, newInstMethods, newClsMethods) diff --git a/JSPatchDemo/JSPatchDemo.xcodeproj/project.pbxproj b/JSPatchDemo/JSPatchDemo.xcodeproj/project.pbxproj index 5e73bbc1..57341849 100644 --- a/JSPatchDemo/JSPatchDemo.xcodeproj/project.pbxproj +++ b/JSPatchDemo/JSPatchDemo.xcodeproj/project.pbxproj @@ -24,6 +24,8 @@ 36F0DC791BF6D5D20090EA4A /* JPLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 36F0DC781BF6D5D20090EA4A /* JPLoader.m */; }; 36F0DCC61BFAF41C0090EA4A /* libz.1.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 36F0DCC51BFAF41C0090EA4A /* libz.1.dylib */; }; 3F6C38EB1B4A37D600F88662 /* JPMemory.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F6C38EA1B4A37D600F88662 /* JPMemory.m */; }; + 6C6CAC741C5F0BCA00444348 /* superTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 6C6CAC721C5F0BCA00444348 /* superTest.js */; }; + 6C6CAC751C5F0BCA00444348 /* SuperTestObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C6CAC731C5F0BCA00444348 /* SuperTestObject.m */; }; 6C72B7961C352BA80086C98D /* newProtocolTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C72B7951C352BA80086C98D /* newProtocolTest.m */; }; 6C9C0EE41C25A7C700FCAAC5 /* newProtocolTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 6C9C0EE31C25A7C700FCAAC5 /* newProtocolTest.js */; }; 6C9C0EE51C25A7DA00FCAAC5 /* newProtocolTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 6C9C0EE31C25A7C700FCAAC5 /* newProtocolTest.js */; }; @@ -93,6 +95,9 @@ 36F0DCC51BFAF41C0090EA4A /* libz.1.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.1.dylib; path = ../../../../../../usr/lib/libz.1.dylib; sourceTree = ""; }; 3F6C38E91B4A37D600F88662 /* JPMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPMemory.h; sourceTree = ""; }; 3F6C38EA1B4A37D600F88662 /* JPMemory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPMemory.m; sourceTree = ""; }; + 6C6CAC711C5F0BCA00444348 /* SuperTestObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SuperTestObject.h; sourceTree = ""; }; + 6C6CAC721C5F0BCA00444348 /* superTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = superTest.js; sourceTree = ""; }; + 6C6CAC731C5F0BCA00444348 /* SuperTestObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SuperTestObject.m; sourceTree = ""; }; 6C72B7941C352BA80086C98D /* newProtocolTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = newProtocolTest.h; sourceTree = ""; }; 6C72B7951C352BA80086C98D /* newProtocolTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = newProtocolTest.m; sourceTree = ""; }; 6C9C0EE31C25A7C700FCAAC5 /* newProtocolTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = newProtocolTest.js; sourceTree = ""; }; @@ -275,6 +280,9 @@ DE94AE271AF246C000E461D4 /* JSPatchTests */ = { isa = PBXGroup; children = ( + 6C6CAC711C5F0BCA00444348 /* SuperTestObject.h */, + 6C6CAC721C5F0BCA00444348 /* superTest.js */, + 6C6CAC731C5F0BCA00444348 /* SuperTestObject.m */, 6C72B7941C352BA80086C98D /* newProtocolTest.h */, 6C72B7951C352BA80086C98D /* newProtocolTest.m */, 6C9C0EE31C25A7C700FCAAC5 /* newProtocolTest.js */, @@ -434,6 +442,7 @@ files = ( DE6FFF031B42B01C0005EE83 /* protocolTest.js in Resources */, 2D0DF7071B22F75C005695DA /* inheritTest.js in Resources */, + 6C6CAC741C5F0BCA00444348 /* superTest.js in Resources */, DE94AE471AF2480000E461D4 /* test.js in Resources */, 6C9C0EE41C25A7C700FCAAC5 /* newProtocolTest.js in Resources */, E1B89EAE1B228818000645C2 /* multithreadTest.js in Resources */, @@ -481,6 +490,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 6C6CAC751C5F0BCA00444348 /* SuperTestObject.m in Sources */, 6C72B7961C352BA80086C98D /* newProtocolTest.m in Sources */, DE94AE461AF2480000E461D4 /* JPTestObject.m in Sources */, E1B89EA31B218986000645C2 /* JPInheritanceTestObjects.m in Sources */, diff --git a/JSPatchDemo/JSPatchDemo/JPViewController.h b/JSPatchDemo/JSPatchDemo/JPViewController.h old mode 100644 new mode 100755 diff --git a/JSPatchDemo/JSPatchTests/JSPatchTests.m b/JSPatchDemo/JSPatchTests/JSPatchTests.m index 4bf3f33f..0c120557 100644 --- a/JSPatchDemo/JSPatchTests/JSPatchTests.m +++ b/JSPatchDemo/JSPatchTests/JSPatchTests.m @@ -16,6 +16,7 @@ #import "newProtocolTest.h" //#import "JPCoreGraphics.h" //#import "JPUIKit.h" +#import "SuperTestObject.h" #import "JPMemory.h" @interface JSPatchTests : XCTestCase @@ -174,6 +175,13 @@ - (void)testEngine { beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]]; } +- (void)testSuperClass +{ + [self loadPatch:@"superTest"]; + SuperTestC *testobject = [[SuperTestC alloc]init]; + [testobject testSuper]; +} + - (void)testInheritance { /*get values before patch*/ diff --git a/JSPatchDemo/JSPatchTests/SuperTestObject.h b/JSPatchDemo/JSPatchTests/SuperTestObject.h new file mode 100644 index 00000000..601b992e --- /dev/null +++ b/JSPatchDemo/JSPatchTests/SuperTestObject.h @@ -0,0 +1,25 @@ +// +// SuperTest.h +// JSPatchDemo +// +// Created by Awhisper on 16/1/28. +// Copyright © 2016年 bang. All rights reserved. +// + +#import + + +@interface SuperTestA : NSObject +-(void)testSuper; +@end + +@interface SuperTestB : SuperTestA + +-(void)testSuper; +@end + +@interface SuperTestC : SuperTestB + +-(void)testSuper; +@end + diff --git a/JSPatchDemo/JSPatchTests/SuperTestObject.m b/JSPatchDemo/JSPatchTests/SuperTestObject.m new file mode 100644 index 00000000..cb9b4d62 --- /dev/null +++ b/JSPatchDemo/JSPatchTests/SuperTestObject.m @@ -0,0 +1,37 @@ +// +// SuperTest.m +// JSPatchDemo +// +// Created by Awhisper on 16/1/28. +// Copyright © 2016年 bang. All rights reserved. +// + +#import "SuperTestObject.h" + +@implementation SuperTestB + +-(void)testSuper +{ + NSLog(@" ==== print test B ==="); +} + +@end + +@implementation SuperTestA + +-(void)testSuper +{ + NSLog(@" === print test A ===="); +} + +@end + +@implementation SuperTestC + +-(void)testSuper +{ + [super testSuper]; + NSLog(@" === print test C ===="); +} + +@end diff --git a/JSPatchDemo/JSPatchTests/superTest.js b/JSPatchDemo/JSPatchTests/superTest.js new file mode 100644 index 00000000..6ba40ddb --- /dev/null +++ b/JSPatchDemo/JSPatchTests/superTest.js @@ -0,0 +1,6 @@ +defineClass('SuperTestB : SuperTestA', { + testSuper: function() { + self.ORIGtestSuper(); + self.super().testSuper(); + } +}) \ No newline at end of file