ObjCCallbackFunction.mm 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. /*
  2. * Copyright (C) 2013 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
  17. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  18. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  20. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  21. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include "config.h"
  26. #import "JavaScriptCore.h"
  27. #if JSC_OBJC_API_ENABLED
  28. #import "APICast.h"
  29. #import "APIShims.h"
  30. #import "Error.h"
  31. #import "JSCJSValueInlines.h"
  32. #import "JSCell.h"
  33. #import "JSCellInlines.h"
  34. #import "JSContextInternal.h"
  35. #import "JSWrapperMap.h"
  36. #import "JSValueInternal.h"
  37. #import "ObjCCallbackFunction.h"
  38. #import "ObjcRuntimeExtras.h"
  39. #import <objc/runtime.h>
  40. #import <wtf/RetainPtr.h>
  41. class CallbackArgument {
  42. public:
  43. virtual ~CallbackArgument();
  44. virtual void set(NSInvocation *, NSInteger, JSContext *, JSValueRef, JSValueRef*) = 0;
  45. OwnPtr<CallbackArgument> m_next;
  46. };
  47. CallbackArgument::~CallbackArgument()
  48. {
  49. }
  50. class CallbackArgumentBoolean : public CallbackArgument {
  51. virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef*) override
  52. {
  53. bool value = JSValueToBoolean([context JSGlobalContextRef], argument);
  54. [invocation setArgument:&value atIndex:argumentNumber];
  55. }
  56. };
  57. template<typename T>
  58. class CallbackArgumentInteger : public CallbackArgument {
  59. virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
  60. {
  61. T value = (T)JSC::toInt32(JSValueToNumber([context JSGlobalContextRef], argument, exception));
  62. [invocation setArgument:&value atIndex:argumentNumber];
  63. }
  64. };
  65. template<typename T>
  66. class CallbackArgumentDouble : public CallbackArgument {
  67. virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
  68. {
  69. T value = (T)JSValueToNumber([context JSGlobalContextRef], argument, exception);
  70. [invocation setArgument:&value atIndex:argumentNumber];
  71. }
  72. };
  73. class CallbackArgumentJSValue : public CallbackArgument {
  74. virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef*) override
  75. {
  76. JSValue *value = [JSValue valueWithJSValueRef:argument inContext:context];
  77. [invocation setArgument:&value atIndex:argumentNumber];
  78. }
  79. };
  80. class CallbackArgumentId : public CallbackArgument {
  81. virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef*) override
  82. {
  83. id value = valueToObject(context, argument);
  84. [invocation setArgument:&value atIndex:argumentNumber];
  85. }
  86. };
  87. class CallbackArgumentOfClass : public CallbackArgument {
  88. public:
  89. CallbackArgumentOfClass(Class cls)
  90. : CallbackArgument()
  91. , m_class(cls)
  92. {
  93. [m_class retain];
  94. }
  95. private:
  96. virtual ~CallbackArgumentOfClass()
  97. {
  98. [m_class release];
  99. }
  100. virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
  101. {
  102. JSGlobalContextRef contextRef = [context JSGlobalContextRef];
  103. id object = tryUnwrapObjcObject(contextRef, argument);
  104. if (object && [object isKindOfClass:m_class]) {
  105. [invocation setArgument:&object atIndex:argumentNumber];
  106. return;
  107. }
  108. if (JSValueIsNull(contextRef, argument) || JSValueIsUndefined(contextRef, argument)) {
  109. object = nil;
  110. [invocation setArgument:&object atIndex:argumentNumber];
  111. return;
  112. }
  113. *exception = toRef(JSC::createTypeError(toJS(contextRef), "Argument does not match Objective-C Class"));
  114. }
  115. Class m_class;
  116. };
  117. class CallbackArgumentNSNumber : public CallbackArgument {
  118. virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
  119. {
  120. id value = valueToNumber([context JSGlobalContextRef], argument, exception);
  121. [invocation setArgument:&value atIndex:argumentNumber];
  122. }
  123. };
  124. class CallbackArgumentNSString : public CallbackArgument {
  125. virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
  126. {
  127. id value = valueToString([context JSGlobalContextRef], argument, exception);
  128. [invocation setArgument:&value atIndex:argumentNumber];
  129. }
  130. };
  131. class CallbackArgumentNSDate : public CallbackArgument {
  132. virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
  133. {
  134. id value = valueToDate([context JSGlobalContextRef], argument, exception);
  135. [invocation setArgument:&value atIndex:argumentNumber];
  136. }
  137. };
  138. class CallbackArgumentNSArray : public CallbackArgument {
  139. virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
  140. {
  141. id value = valueToArray([context JSGlobalContextRef], argument, exception);
  142. [invocation setArgument:&value atIndex:argumentNumber];
  143. }
  144. };
  145. class CallbackArgumentNSDictionary : public CallbackArgument {
  146. virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
  147. {
  148. id value = valueToDictionary([context JSGlobalContextRef], argument, exception);
  149. [invocation setArgument:&value atIndex:argumentNumber];
  150. }
  151. };
  152. class CallbackArgumentStruct : public CallbackArgument {
  153. public:
  154. CallbackArgumentStruct(NSInvocation *conversionInvocation, const char* encodedType)
  155. : m_conversionInvocation(conversionInvocation)
  156. , m_buffer(encodedType)
  157. {
  158. }
  159. private:
  160. virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef*) override
  161. {
  162. JSValue *value = [JSValue valueWithJSValueRef:argument inContext:context];
  163. [m_conversionInvocation invokeWithTarget:value];
  164. [m_conversionInvocation getReturnValue:m_buffer];
  165. [invocation setArgument:m_buffer atIndex:argumentNumber];
  166. }
  167. RetainPtr<NSInvocation> m_conversionInvocation;
  168. StructBuffer m_buffer;
  169. };
  170. class ArgumentTypeDelegate {
  171. public:
  172. typedef CallbackArgument* ResultType;
  173. template<typename T>
  174. static ResultType typeInteger()
  175. {
  176. return new CallbackArgumentInteger<T>;
  177. }
  178. template<typename T>
  179. static ResultType typeDouble()
  180. {
  181. return new CallbackArgumentDouble<T>;
  182. }
  183. static ResultType typeBool()
  184. {
  185. return new CallbackArgumentBoolean;
  186. }
  187. static ResultType typeVoid()
  188. {
  189. RELEASE_ASSERT_NOT_REACHED();
  190. return 0;
  191. }
  192. static ResultType typeId()
  193. {
  194. return new CallbackArgumentId;
  195. }
  196. static ResultType typeOfClass(const char* begin, const char* end)
  197. {
  198. StringRange copy(begin, end);
  199. Class cls = objc_getClass(copy);
  200. if (!cls)
  201. return 0;
  202. if (cls == [JSValue class])
  203. return new CallbackArgumentJSValue;
  204. if (cls == [NSString class])
  205. return new CallbackArgumentNSString;
  206. if (cls == [NSNumber class])
  207. return new CallbackArgumentNSNumber;
  208. if (cls == [NSDate class])
  209. return new CallbackArgumentNSDate;
  210. if (cls == [NSArray class])
  211. return new CallbackArgumentNSArray;
  212. if (cls == [NSDictionary class])
  213. return new CallbackArgumentNSDictionary;
  214. return new CallbackArgumentOfClass(cls);
  215. }
  216. static ResultType typeBlock(const char*, const char*)
  217. {
  218. return nil;
  219. }
  220. static ResultType typeStruct(const char* begin, const char* end)
  221. {
  222. StringRange copy(begin, end);
  223. if (NSInvocation *invocation = valueToTypeInvocationFor(copy))
  224. return new CallbackArgumentStruct(invocation, copy);
  225. return 0;
  226. }
  227. };
  228. class CallbackResult {
  229. public:
  230. virtual ~CallbackResult()
  231. {
  232. }
  233. virtual JSValueRef get(NSInvocation *, JSContext *, JSValueRef*) = 0;
  234. };
  235. class CallbackResultVoid : public CallbackResult {
  236. virtual JSValueRef get(NSInvocation *, JSContext *context, JSValueRef*) override
  237. {
  238. return JSValueMakeUndefined([context JSGlobalContextRef]);
  239. }
  240. };
  241. class CallbackResultId : public CallbackResult {
  242. virtual JSValueRef get(NSInvocation *invocation, JSContext *context, JSValueRef*) override
  243. {
  244. id value;
  245. [invocation getReturnValue:&value];
  246. return objectToValue(context, value);
  247. }
  248. };
  249. template<typename T>
  250. class CallbackResultNumeric : public CallbackResult {
  251. virtual JSValueRef get(NSInvocation *invocation, JSContext *context, JSValueRef*) override
  252. {
  253. T value;
  254. [invocation getReturnValue:&value];
  255. return JSValueMakeNumber([context JSGlobalContextRef], value);
  256. }
  257. };
  258. class CallbackResultBoolean : public CallbackResult {
  259. virtual JSValueRef get(NSInvocation *invocation, JSContext *context, JSValueRef*) override
  260. {
  261. bool value;
  262. [invocation getReturnValue:&value];
  263. return JSValueMakeBoolean([context JSGlobalContextRef], value);
  264. }
  265. };
  266. class CallbackResultStruct : public CallbackResult {
  267. public:
  268. CallbackResultStruct(NSInvocation *conversionInvocation, const char* encodedType)
  269. : m_conversionInvocation(conversionInvocation)
  270. , m_buffer(encodedType)
  271. {
  272. }
  273. private:
  274. virtual JSValueRef get(NSInvocation *invocation, JSContext *context, JSValueRef*) override
  275. {
  276. [invocation getReturnValue:m_buffer];
  277. [m_conversionInvocation setArgument:m_buffer atIndex:2];
  278. [m_conversionInvocation setArgument:&context atIndex:3];
  279. [m_conversionInvocation invokeWithTarget:[JSValue class]];
  280. JSValue *value;
  281. [m_conversionInvocation getReturnValue:&value];
  282. return valueInternalValue(value);
  283. }
  284. RetainPtr<NSInvocation> m_conversionInvocation;
  285. StructBuffer m_buffer;
  286. };
  287. class ResultTypeDelegate {
  288. public:
  289. typedef CallbackResult* ResultType;
  290. template<typename T>
  291. static ResultType typeInteger()
  292. {
  293. return new CallbackResultNumeric<T>;
  294. }
  295. template<typename T>
  296. static ResultType typeDouble()
  297. {
  298. return new CallbackResultNumeric<T>;
  299. }
  300. static ResultType typeBool()
  301. {
  302. return new CallbackResultBoolean;
  303. }
  304. static ResultType typeVoid()
  305. {
  306. return new CallbackResultVoid;
  307. }
  308. static ResultType typeId()
  309. {
  310. return new CallbackResultId();
  311. }
  312. static ResultType typeOfClass(const char*, const char*)
  313. {
  314. return new CallbackResultId();
  315. }
  316. static ResultType typeBlock(const char*, const char*)
  317. {
  318. return new CallbackResultId();
  319. }
  320. static ResultType typeStruct(const char* begin, const char* end)
  321. {
  322. StringRange copy(begin, end);
  323. if (NSInvocation *invocation = typeToValueInvocationFor(copy))
  324. return new CallbackResultStruct(invocation, copy);
  325. return 0;
  326. }
  327. };
  328. enum CallbackType {
  329. CallbackInstanceMethod,
  330. CallbackClassMethod,
  331. CallbackBlock
  332. };
  333. namespace JSC {
  334. class ObjCCallbackFunctionImpl {
  335. public:
  336. ObjCCallbackFunctionImpl(JSContext *context, NSInvocation *invocation, CallbackType type, Class instanceClass, PassOwnPtr<CallbackArgument> arguments, PassOwnPtr<CallbackResult> result)
  337. : m_context(context)
  338. , m_type(type)
  339. , m_instanceClass([instanceClass retain])
  340. , m_invocation(invocation)
  341. , m_arguments(arguments)
  342. , m_result(result)
  343. {
  344. ASSERT(type != CallbackInstanceMethod || instanceClass);
  345. }
  346. ~ObjCCallbackFunctionImpl()
  347. {
  348. if (m_type != CallbackInstanceMethod)
  349. [[m_invocation.get() target] release];
  350. [m_instanceClass release];
  351. }
  352. JSValueRef call(JSContext *context, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
  353. JSContext *context()
  354. {
  355. return m_context.get();
  356. }
  357. void setContext(JSContext *context)
  358. {
  359. ASSERT(!m_context.get());
  360. m_context.set(context);
  361. }
  362. id wrappedBlock()
  363. {
  364. return m_type == CallbackBlock ? [m_invocation target] : nil;
  365. }
  366. private:
  367. WeakContextRef m_context;
  368. CallbackType m_type;
  369. Class m_instanceClass;
  370. RetainPtr<NSInvocation> m_invocation;
  371. OwnPtr<CallbackArgument> m_arguments;
  372. OwnPtr<CallbackResult> m_result;
  373. };
  374. static JSValueRef objCCallbackFunctionCallAsFunction(JSContextRef callerContext, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
  375. {
  376. // Retake the API lock - we need this for a few reasons:
  377. // (1) We don't want to support the C-API's confusing drops-locks-once policy - should only drop locks if we can do so recursively.
  378. // (2) We're calling some JSC internals that require us to be on the 'inside' - e.g. createTypeError.
  379. // (3) We need to be locked (per context would be fine) against conflicting usage of the ObjCCallbackFunction's NSInvocation.
  380. JSC::APIEntryShim entryShim(toJS(callerContext));
  381. ObjCCallbackFunction* callback = static_cast<ObjCCallbackFunction*>(toJS(function));
  382. ObjCCallbackFunctionImpl* impl = callback->impl();
  383. JSContext *context = impl->context();
  384. if (!context) {
  385. context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(toJS(callerContext)->lexicalGlobalObject()->globalExec())];
  386. impl->setContext(context);
  387. }
  388. CallbackData callbackData;
  389. JSValueRef result;
  390. @autoreleasepool {
  391. [context beginCallbackWithData:&callbackData thisValue:thisObject argumentCount:argumentCount arguments:arguments];
  392. result = impl->call(context, thisObject, argumentCount, arguments, exception);
  393. if (context.exception)
  394. *exception = valueInternalValue(context.exception);
  395. [context endCallbackWithData:&callbackData];
  396. }
  397. return result;
  398. }
  399. const JSC::ClassInfo ObjCCallbackFunction::s_info = { "CallbackFunction", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(ObjCCallbackFunction) };
  400. ObjCCallbackFunction::ObjCCallbackFunction(JSC::JSGlobalObject* globalObject, JSObjectCallAsFunctionCallback callback, PassOwnPtr<ObjCCallbackFunctionImpl> impl)
  401. : Base(globalObject, globalObject->objcCallbackFunctionStructure(), callback)
  402. , m_impl(impl)
  403. {
  404. }
  405. ObjCCallbackFunction* ObjCCallbackFunction::create(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject, const String& name, PassOwnPtr<ObjCCallbackFunctionImpl> impl)
  406. {
  407. ObjCCallbackFunction* function = new (NotNull, allocateCell<ObjCCallbackFunction>(*exec->heap())) ObjCCallbackFunction(globalObject, objCCallbackFunctionCallAsFunction, impl);
  408. function->finishCreation(exec->vm(), name);
  409. return function;
  410. }
  411. void ObjCCallbackFunction::destroy(JSCell* cell)
  412. {
  413. static_cast<ObjCCallbackFunction*>(cell)->ObjCCallbackFunction::~ObjCCallbackFunction();
  414. }
  415. JSValueRef ObjCCallbackFunctionImpl::call(JSContext *context, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
  416. {
  417. JSGlobalContextRef contextRef = [context JSGlobalContextRef];
  418. size_t firstArgument;
  419. switch (m_type) {
  420. case CallbackInstanceMethod: {
  421. id target = tryUnwrapObjcObject(contextRef, thisObject);
  422. if (!target || ![target isKindOfClass:m_instanceClass]) {
  423. *exception = toRef(JSC::createTypeError(toJS(contextRef), "self type check failed for Objective-C instance method"));
  424. return JSValueMakeUndefined(contextRef);
  425. }
  426. [m_invocation setTarget:target];
  427. }
  428. // fallthrough - firstArgument for CallbackInstanceMethod is also 2!
  429. case CallbackClassMethod:
  430. firstArgument = 2;
  431. break;
  432. case CallbackBlock:
  433. firstArgument = 1;
  434. }
  435. size_t argumentNumber = 0;
  436. for (CallbackArgument* argument = m_arguments.get(); argument; argument = argument->m_next.get()) {
  437. JSValueRef value = argumentNumber < argumentCount ? arguments[argumentNumber] : JSValueMakeUndefined(contextRef);
  438. argument->set(m_invocation.get(), argumentNumber + firstArgument, context, value, exception);
  439. if (*exception)
  440. return JSValueMakeUndefined(contextRef);
  441. ++argumentNumber;
  442. }
  443. [m_invocation invoke];
  444. return m_result->get(m_invocation.get(), context, exception);
  445. }
  446. } // namespace JSC
  447. static bool blockSignatureContainsClass()
  448. {
  449. static bool containsClass = ^{
  450. id block = ^(NSString *string){ return string; };
  451. return _Block_has_signature(block) && strstr(_Block_signature(block), "NSString");
  452. }();
  453. return containsClass;
  454. }
  455. inline bool skipNumber(const char*& position)
  456. {
  457. if (!isASCIIDigit(*position))
  458. return false;
  459. while (isASCIIDigit(*++position)) { }
  460. return true;
  461. }
  462. static JSObjectRef objCCallbackFunctionForInvocation(JSContext *context, NSInvocation *invocation, CallbackType type, Class instanceClass, const char* signatureWithObjcClasses)
  463. {
  464. const char* position = signatureWithObjcClasses;
  465. OwnPtr<CallbackResult> result = adoptPtr(parseObjCType<ResultTypeDelegate>(position));
  466. if (!result || !skipNumber(position))
  467. return nil;
  468. switch (type) {
  469. case CallbackInstanceMethod:
  470. case CallbackClassMethod:
  471. // Methods are passed two implicit arguments - (id)self, and the selector.
  472. if ('@' != *position++ || !skipNumber(position) || ':' != *position++ || !skipNumber(position))
  473. return nil;
  474. break;
  475. case CallbackBlock:
  476. // Blocks are passed one implicit argument - the block, of type "@?".
  477. if (('@' != *position++) || ('?' != *position++) || !skipNumber(position))
  478. return nil;
  479. // Only allow arguments of type 'id' if the block signature contains the NS type information.
  480. if ((!blockSignatureContainsClass() && strchr(position, '@')))
  481. return nil;
  482. break;
  483. }
  484. OwnPtr<CallbackArgument> arguments = 0;
  485. OwnPtr<CallbackArgument>* nextArgument = &arguments;
  486. unsigned argumentCount = 0;
  487. while (*position) {
  488. OwnPtr<CallbackArgument> argument = adoptPtr(parseObjCType<ArgumentTypeDelegate>(position));
  489. if (!argument || !skipNumber(position))
  490. return nil;
  491. *nextArgument = argument.release();
  492. nextArgument = &(*nextArgument)->m_next;
  493. ++argumentCount;
  494. }
  495. JSC::ExecState* exec = toJS([context JSGlobalContextRef]);
  496. JSC::APIEntryShim shim(exec);
  497. OwnPtr<JSC::ObjCCallbackFunctionImpl> impl = adoptPtr(new JSC::ObjCCallbackFunctionImpl(context, invocation, type, instanceClass, arguments.release(), result.release()));
  498. // FIXME: Maybe we could support having the selector as the name of the function to make it a bit more user-friendly from the JS side?
  499. return toRef(JSC::ObjCCallbackFunction::create(exec, exec->lexicalGlobalObject(), "", impl.release()));
  500. }
  501. JSObjectRef objCCallbackFunctionForMethod(JSContext *context, Class cls, Protocol *protocol, BOOL isInstanceMethod, SEL sel, const char* types)
  502. {
  503. NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:types]];
  504. [invocation setSelector:sel];
  505. if (!isInstanceMethod)
  506. [invocation setTarget:cls];
  507. return objCCallbackFunctionForInvocation(context, invocation, isInstanceMethod ? CallbackInstanceMethod : CallbackClassMethod, isInstanceMethod ? cls : nil, _protocol_getMethodTypeEncoding(protocol, sel, YES, isInstanceMethod));
  508. }
  509. JSObjectRef objCCallbackFunctionForBlock(JSContext *context, id target)
  510. {
  511. if (!_Block_has_signature(target))
  512. return 0;
  513. const char* signature = _Block_signature(target);
  514. NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:signature]];
  515. [invocation setTarget:[target copy]];
  516. return objCCallbackFunctionForInvocation(context, invocation, CallbackBlock, nil, signature);
  517. }
  518. id tryUnwrapBlock(JSObjectRef object)
  519. {
  520. if (!toJS(object)->inherits(&JSC::ObjCCallbackFunction::s_info))
  521. return nil;
  522. return static_cast<JSC::ObjCCallbackFunction*>(toJS(object))->impl()->wrappedBlock();
  523. }
  524. #endif