1

Supposed to have a completion block like

typedef void(^JSAPICallback)(id result);

and a binding class

@protocol JSProtocol<JSExport>

- (void)initAPI:(JSAPICallback)success;

@end

@interface JSObject : NSObject<JSProtocol>
- (void)initAPI:(JSAPICallback)success error:(JSAPICallback)error;
@end

@implementation JSObject
- (void)initAPI:(JSAPICallback)success  {
    [[API sharedInstance] initialize:^(id results, NSError *error) {
        if(error==nil) {
            success(results)
        } else {
            error()
       }
    }];
}
}

If I try to bind it in a JSContext in this case in a tvOS TVApplicationControllerDelegate delegate like:

- (void)appController:(TVApplicationController *)appController evaluateAppJavaScriptInContext:(JSContext *)jsContext {

    JSObject *jsObject = [[JSObject alloc] init];
    [jsContext setObject:jsObject forKeyedSubscript:@"jsobject"];
    [jsContext setExceptionHandler:^(JSContext *context, JSValue *value) {
        NSLog(@"%@", value);
    }];
}

I have a crash:

2015-10-09 23:33:16.669 TestbedTV[9707:3524754] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000011008f105 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010fb07deb objc_exception_throw + 48
    2   CoreFoundation                      0x000000010ff9206e -[__NSPlaceholderDictionary initWithObjects:forKeys:count:] + 318
    3   CoreFoundation                      0x000000010ffa43bb +[NSDictionary dictionaryWithObjects:forKeys:count:] + 59
    4   JavaScriptCore                      0x000000011905d388 -[JSObjCClassInfo allocateConstructorAndPrototype] + 2664
    5   JavaScriptCore                      0x000000011905e25f -[JSObjCClassInfo prototype] + 47
    6   JavaScriptCore                      0x000000011905e0ab -[JSObjCClassInfo wrapperForObject:] + 587
    7   JavaScriptCore                      0x000000011905e737 -[JSWrapperMap jsWrapperForObject:] + 423
    8   JavaScriptCore                      0x0000000118fdce80 -[JSContext(Internal) wrapperForObjCObject:] + 64
    9   JavaScriptCore                      0x0000000119054238 _ZL24objectToValueWithoutCopyP9JSContextP11objc_object + 760
    10  JavaScriptCore                      0x000000011905053a _Z13objectToValueP9JSContextP11objc_object + 74
    11  JavaScriptCore                      0x0000000119051ad9 -[JSValue setValue:forProperty:] + 137
    12  TestbedTV                           0x000000010eeb42cd -[AppDelegate appController:evaluateAppJavaScriptInContext:] + 141
    13  TVMLKit                             0x000000011048d3be -[TVApplicationController appContext:evaluateAppJavaScriptInContext:] + 889
    14  ITMLKit                             0x000000011b47d431 -[IKAppContext(JS) evaluateFoundationJS] + 2566
    15  ITMLKit                             0x000000011b4a56b3 -[IKAppContext _startWithScript:scriptUrl:] + 262
    16  ITMLKit                             0x000000011b4a52a5 -[IKAppContext _startWithURL:urlTrusted:] + 1277
    17  ITMLKit                             0x000000011b4a37e7 __21-[IKAppContext start]_block_invoke + 46
    18  ITMLKit                             0x000000011b4a6633 -[IKAppContext _sourcePerform] + 379
    19  ITMLKit                             0x000000011b4a647d IKRunLoopSourcePerformCallBack + 34
    20  CoreFoundation                      0x000000010ffbb1b1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    21  CoreFoundation                      0x000000010ffb10dc __CFRunLoopDoSources0 + 556
    22  CoreFoundation                      0x000000010ffb0593 __CFRunLoopRun + 867
    23  CoreFoundation                      0x000000010ffaffa8 CFRunLoopRunSpecific + 488
    24  CoreFoundation                      0x0000000110063201 CFRunLoopRun + 97
    25  ITMLKit                             0x000000011b4a62ea -[IKAppContext _jsThreadMain] + 337
    26  Foundation                          0x000000010f79224b __NSThread__start__ + 1198
    27  libsystem_pthread.dylib             0x000000011311505a _pthread_body + 131
    28  libsystem_pthread.dylib             0x0000000113114fd7 _pthread_body + 0
    29  libsystem_pthread.dylib             0x00000001131123ed thread_start + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException

It seems that the JavaScriptCore is not able to bind the completion block. Having a simple function with simple parameters like this

@protocol JSProtocol<JSExport>
- (void)initAPI:(NSString*)options;
@end

instead the binding would work as expected. This happens in tvOS9.0, but I think it would crash in iOS9.1 as well.

The most likely question to get some idea is ObjectiveC and JavaScriptCore: Will using this method of calling CallBacks cause memory issues?.

Community
  • 1
  • 1
loretoparisi
  • 15,724
  • 11
  • 102
  • 146
  • I'm a little confused, because your code doesn't match the crash. Specifically, the crash log says `[AppDelegate appController:evaluateAppJavaScriptInContext:]` called `[JSValue setValue:forProperty:]` but I see no such call. Is this the posted code the exact code that produce the posted crash log? – Doug Richardson Dec 10 '15 at 04:30
  • @DougRichardson that's right, I missed the JavaScript part. – loretoparisi Dec 10 '15 at 13:57
  • When you say you missed the JavaScript part, are you saying there is more to `[AppDelegate appController:evaluateAppJavaScriptInContext:]` than you posted above? – Doug Richardson Dec 10 '15 at 18:33
  • @DougRichardson So at the end I have found the solution, I have explained it here (where is the javascript "working" counterpart as well) http://stackoverflow.com/questions/33081565/how-to-bridge-tvml-javascriptcore-to-uikit-objective-c-swift – loretoparisi Dec 11 '15 at 00:03

0 Answers0