Search code examples
objective-cmacosjavascriptcore

How to Conditionally Use JSExport Protocol in 10.7+ apps?


I am writing an app that has a minimum deployment target of 10.7. As such, whenever I try to include a protocol that conforms to JSExport, the compiler says that it cannot find the protocol declaration for 'JSExport'.

If I set the minimum deployment target up to 10.9 it compiles just fine. Here is an example of noncompiling code.

#import <Cocoa/Cocoa.h>
#import <JavaScriptCore/JavaScriptCore.h>
#import <WebKit/WebKit.h>

@protocol MyJSExport <JSExport>
-(void)doSomething;
@end

I've tried dynamically creating MyJSExport protocol at runtime by following the example set here, but their conclusion was that it didn't work.

So how do you write a protocol that conforms to JSExport while maintaining a 10.7 minimum deployment target?


Solution

  • The JSExport protocol causes Javascript getter/setters to be defined for properties in your protocol and Javascript wrapper functions to be defined for methods defined in your protocol.

    It didn't exist before 10.9.

    The answer depends on what behaviour are you expecting for targets less than 10.9

    Assuming you just expect to silently ignore this functionality in older targets, then inspecting <JSExport.h> provides a clue on how you might do this - by inserting your own empty protocol for JSExport (just as <JSExport.h> does) if it is not already defined (as shown below), gives you code that doesn't need to change when you compile for 10.7 vs 10.9

    But: inspecting the JavaScriptCore headers, I would expect that the rest of the Objective-C Javascript bridge functionality introduced with 10.9 will be disabled until you compile for a target of 10.9 - are you using JSContext or JSValue?

    #import <Cocoa/Cocoa.h>
    #import <JavaScriptCore/JavaScriptCore.h>
    #import <WebKit/WebKit.h>
    
    // Check if JSExport functionality is available
    #if !JSC_OBJC_API_ENABLED
    @protocol JSExport
    @end
    #endif
    
    @protocol MyJSExport <JSExport>
    -(void)doSomething;
    @end