Permalink
Browse files

Add '.performSelectorInOC(sel, args, cb)' function:

When calling OC method in JS, the OC method will be exexuted within the JavaScriptCore context lock, so if we call OC methods concurrently in JS, this methods will execute serially because of the JSCore lock. '.performSelectorInOC()' can perform an OC method outside of the JS context, so it can get rid of the JSCore lock and execute OC methods concurrently.

Usage:

```
//OC
@implementation JPObject
- (id)methodA:(NSString *)str
{
	return str;
}
- (id)methodB
{
	return nil;
}
@EnD
```

```
//JS original
defineClass('JPObject', {
	methodB: function(){
		var str = "_append";
		//perform methodA within JSCore lock
		var ret = self.methodA('stringFromJS') + str;
		return ret;
	}
})
console.log(JPObject.alloc().init().methodB())   //output "stringFromJS_append"
```

```
//JS using .performSelectorInOC()
defineClass('JPObject', {
	methodB: function(){
		var str = "_append";
		//perform methodA outside of the JSCore lock
		return self.performSelectorInOC('methodA:', ['stringFromJS'], function(ret){
			ret = ret + str
			return str;
		})
	}
})
console.log(JPObject.alloc().init().methodB())   //output "stringFromJS_append"
```
  • Loading branch information...
bang590 committed Nov 4, 2015
1 parent 90bdf9b commit 6e2ab4f5eb750d364134f2eaac5483373d289972
Showing with 23 additions and 6 deletions.
  1. +12 −2 JSPatch/JPEngine.m
  2. +11 −4 JSPatch/JSPatch.js
View
@@ -539,7 +539,18 @@ static void JPForwardInvocation(id slf, SEL selector, NSInvocation *invocation)
JSValue *jsval; \
[_JSMethodForwardCallLock lock]; \
jsval = [fun callWithArguments:params]; \
[_JSMethodForwardCallLock unlock];
[_JSMethodForwardCallLock unlock]; \
while (![jsval isNull] && ![jsval isUndefined] && [jsval hasProperty:@"__isPerformInOC"]) { \
NSArray *args = nil; \
JSValue *cb = jsval[@"cb"]; \
if ([jsval hasProperty:@"sel"]) { \
id callRet = callSelector(![jsval[@"clsName"] isUndefined] ? [jsval[@"clsName"] toString] : nil, [jsval[@"sel"] toString], jsval[@"args"], ![jsval[@"obj"] isUndefined] ? jsval[@"obj"] : nil, NO); \
args = @[[_context[@"_formatOCToJS"] callWithArguments:callRet ? @[callRet] : _formatOCToJSList(@[_nilObj])]]; \
} \
[_JSMethodForwardCallLock lock]; \
jsval = [cb callWithArguments:args]; \
[_JSMethodForwardCallLock unlock]; \
}
#define JP_FWD_RET_CASE_RET(_typeChar, _type, _retCode) \
case _typeChar : { \
@@ -579,7 +590,6 @@ static void JPForwardInvocation(id slf, SEL selector, NSInvocation *invocation)
}
JP_FWD_RET_CASE_RET('@', id, JP_FWD_RET_CODE_ID)
JP_FWD_RET_CASE_RET('^', void*, JP_FWD_RET_CODE_POINTER)
JP_FWD_RET_CASE_RET('*', void*, JP_FWD_RET_CODE_POINTER)
JP_FWD_RET_CASE_RET('#', Class, JP_FWD_RET_CODE_CLASS)
View
@@ -84,10 +84,17 @@ var global = this
}
}
if (methodName == 'performSelector') {
return function(){
var args = Array.prototype.slice.call(arguments)
return _methodFunc(self.__obj, self.__clsName, args[0], args.splice(1), self.__isSuper, true)
if (methodName.indexOf('performSelector') > -1) {
if (methodName == 'performSelector') {
return function(){
var args = Array.prototype.slice.call(arguments)
return _methodFunc(self.__obj, self.__clsName, args[0], args.splice(1), self.__isSuper, true)
}
} else if (methodName == 'performSelectorInOC') {
return function(){
var args = Array.prototype.slice.call(arguments)
return {__isPerformInOC:1, obj:self.__obj, clsName:self.__clsName, sel: args[0], args: args[1], cb: args[2]}
}
}
}
return function(){

0 comments on commit 6e2ab4f

Please sign in to comment.