Protocol

JSExport

The protocol you implement to export Objective-C classes and their instance methods, class methods, and properties to JavaScript code.

Declaration

protocol JSExport

Overview

Exporting Objective-C Objects to JavaScript

When you create a JavaScript value from an instance of an Objective-C class, and the JSValue class does not specify a copying convention, JavaScriptCore creates a JavaScript wrapper object. (For certain classes, JavaScriptCore automatically copies values to the appropriate JavaScript type; for example, NSString instances become JavaScript strings.)

In JavaScript, inheritance is supported via a chain of prototype objects. For each Objective-C class you export, JavaScriptCore creates a prototype within the enclosing JavaScript context (a JSContext object). For the NSObject class, the prototype object is the JavaScript context's Object prototype. For all other Objective-C classes, JavaScriptCore creates a prototype object whose internal [Prototype] property points to the prototype property created for the Objective-C class's superclass. As such, the prototype chain for a JavaScript wrapper object reflects the wrapped Objective-C type's inheritance hierarchy.

In addition to the prototype object, JavaScriptCore produces a JavaScript constructor object for each Objective-C class.

Exposing Objective-C Methods and Properties to JavaScript

By default, no methods or properties of the Objective-C class are exposed to JavaScript; instead, you must choose methods and properties to export. For each protocol that a class conforms to, if the protocol incorporates the JSExport protocol, then JavaScriptCore interprets that protocol as a list of methods and properties to be exported to JavaScript.

For each instance method exported, JavaScriptCore creates a corresponding JavaScript function as a property of the prototype object. For each Objective-C property exported, JavaScriptCore creates a JavaScript accessor property on the prototype. For each class method exported, JavaScriptCore creates a JavaScript function on the constructor object. For example, Listing 1 and Listing 2 illustrate adoption of the JSExport protocol and the API presented by an exported class in JavaScript.

Listing 1

Exporting an Objective-C Class to JavaScript

@protocol MyPointExports <JSExport>
@property double x;
@property double y;
- (NSString *)description;
- (instancetype)initWithX:(double)x y:(double)y;
+ (MyPoint *)makePointWithX:(double)x y:(double)y;
@end
 
@interface MyPoint : NSObject <MyPointExports>
- (void)myPrivateMethod;  // Not in the MyPointExports protocol, so not visible to JavaScript code.
@end
 
@implementation MyPoint
// ...
@end
Listing 2

Using an Exported Objective-C Class from JavaScript

// Objective-C properties become fields.
point.x;
point.x = 10;
// Objective-C instance methods become functions.
point.description();
// Objective-C initializers can be called with constructor syntax.
var p = MyPoint(1, 2);
// Objective-C class methods become functions on the constructor object.
var q = MyPoint.makePointWithXY(0, 0);

The attributes of an Objective-C @property declaration determine the attributes of the corresponding JavaScript property:

  • If the Objective-C property is declared readonly, the JavaScript property has the attributes writable: false, enumerable: false, configurable: true.

  • If the Objective-C property is declared readwrite, the JavaScript property has the attributes writable: true, enumerable: true, configurable: true.

Wrapped Objective-C properties, parameters, and return values convert according to the copying convention specified by the JSValue class for their types. . See JSValue for the complete list of copying conventions.

Customizing Export of Objective-C Selectors

When exporting a selector that takes one or more arguments, JavaScriptCore generates a corresponding function name using the following conversion:

  • All colons are removed from the selector.

  • Any lowercase letter that had followed a colon is capitalized.

For example, under the default conversion the Objective-C selector doFoo:withBar: is exported as the JavaScript function doFooWithBar.

To rename a selector exported to JavaScript, use the JSExportAs macro. For example, to instead export the Objective-C selector doFoo:withBar: as the JavaScript function doFoo, use the following declaration:

@protocol MyClassJavaScriptMethods <JSExport>
JSExportAs(doFoo,
- (void)doFoo:(id)foo withBar:(id)bar
);
@end