Last active
December 27, 2015 19:49
-
-
Save MarkVillacampa/7379799 to your computer and use it in GitHub Desktop.
Trying to add methods at runtime for the JSExport protocol in JavaScriptCore. As-is, the method is not called from Javascript. Uncomment lines 7-8 and the end of 11, comment line 65, and run. The method is now called from JavaSript. Any idea why?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
#import <JavaScriptCore/JavaScriptCore.h> | |
#import <objc/runtime.h> | |
const char *_protocol_getMethodTypeEncoding(Protocol *, SEL, BOOL isRequiredMethod, BOOL isInstanceMethod); | |
//@protocol MyProtocol <JSExport> | |
// -(void)one:(id)one; | |
//@end | |
@interface MyClass : NSObject //<MyProtocol> | |
-(void)one:(id)one; | |
+(Protocol*)getProtocol:(NSString*)protocol; | |
+(void)addProtocol:(NSString*)protocol extendingProtocol:(NSString*)extends withMethods:(NSArray*)methods; | |
@end | |
@implementation MyClass : NSObject | |
-(void)one:(id)one | |
{ | |
NSLog(@"Hello!"); | |
} | |
+(void)addProtocol:(NSString*)protocol extendingProtocol:(NSString*)extends withMethods:(NSArray*)methods; | |
{ | |
Protocol *prot = [self getProtocol:protocol]; | |
if (extends != nil) | |
{ | |
protocol_addProtocol(prot, objc_getProtocol([extends UTF8String])); | |
} | |
if (methods != nil) | |
{ | |
for(NSString *method in methods) | |
{ | |
bool instance = true; | |
Method m = class_getInstanceMethod(self, NSSelectorFromString(method)); | |
if (m == nil) | |
{ | |
instance = false; | |
m = class_getClassMethod(self, NSSelectorFromString(method)); | |
} | |
const char *types = method_getTypeEncoding(m); | |
protocol_addMethodDescription(prot, NSSelectorFromString(method), types, true, instance); | |
} | |
} | |
objc_registerProtocol(prot); | |
class_addProtocol([self class], prot); | |
} | |
+(Protocol*)getProtocol:(NSString*)protocol | |
{ | |
Protocol *prot = objc_getProtocol([protocol UTF8String]); | |
if (prot == nil) | |
{ | |
prot = objc_allocateProtocol([protocol UTF8String]); | |
} | |
return prot; | |
} | |
@end | |
int main(int argc, char *argv[]) { | |
@autoreleasepool { | |
@protocol(JSExport); // Stub needed to "see" the protocol at runtime. | |
[MyClass addProtocol:@"MyProtocol" extendingProtocol:@"JSExport" withMethods: @[@"one:"]]; | |
JSContext *context = JSContext.new; | |
// MyClass *myclass = MyClass.class; | |
// context[@"Myclass"] = myclass; | |
// [context evaluateScript:@"Myclass.one()"]; | |
NSLog(@"Conforms to JSExport: %d", class_conformsToProtocol(NSClassFromString(@"MyClass"), objc_getProtocol([@"JSExport" UTF8String]))); | |
NSLog(@"Conforms to MyProtocol: %d", class_conformsToProtocol(NSClassFromString(@"MyClass"), objc_getProtocol([@"MyProtocol" UTF8String]))); | |
uint *outCount; | |
protocol_copyMethodDescriptionList(objc_getProtocol([@"MyProtocol" UTF8String]), true, true, &outCount); | |
protocol_copyMethodDescriptionList(objc_getProtocol([@"MyProtocol" UTF8String]), true, true, &outCount); | |
NSLog(@"Types: %s", protocol_getMethodDescription(NSProtocolFromString(@"MyProtocol"),NSSelectorFromString(@"one:"), true, true).types); | |
NSLog(@"Types internal: %s", _protocol_getMethodTypeEncoding(NSProtocolFromString(@"MyProtocol"),NSSelectorFromString(@"one:"), true, true)); | |
NSLog(@"Number of methods in MyProtocol: %i", outCount); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
fwiw this is one of the biggest reasons I ditched JS and went with Lua for my app's extension stuff