JavaScript Cocoa - JSCocoa
JavaScript Cocoa tasks access the Cocoa framework via the JSCocoa bridge.
JSCocoa provides a bridge between the JavaScript and Objective-C programming languages.
Limitations
Native JavaScript prohibits access to the operating system.
However, using JSCocoa it is possible to escape the sandbox and access the operating system directly, for example, to permit file access or launch new processes using NSTask.
function kosmicTask()
{
// form our image file result path
// this file will be automatically deleted when the task ends.
var path = KosmicTaskController.resultFileWithName('capture.png');
// capture screen shot to file
var task = NSTask.launchedTaskWithLaunchPath_arguments('/usr/sbin/screenCapture', ['-t', 'png', path]);
task.waitUntilExit;
// form result dictionary
var result = {kosmicFile: path};
return result
}
Calling the Task Run Function
KosmicTask JavaScript powered tasks are initiated by calling the Run Function defined in the task Settings. In the following example the task Run Function is set to kosmicTask.
function kosmicTask()
{
// return our string result
return 'Hello, kosmos!';
}
Result Objects
Tasks written in JavaScript Cocoa can return native JavaScript objects or Cocoa objects as task results. The JSCocoa bridge ensures that all objects are coerced as required.
function kosmicTask()
{
// return NSArray
return NSArray.arrayWithArray(["item 1", "item 2"])
}
Result File Handling
KosmicTask supports the returning of file contents within task results.
KosmicTask automatically looks for a kosmicFile record containing file paths within a dictionary type result object. If found, KosmicTask will return the contents of the file or files to the client.
For JavaScript Cocoa powered tasks files are returned as results using the following syntax:
var result = {kosmicFile: path};
A common usage scenario is that a task creates a temporary file (or files) whose contents are then returned to the client. KosmicTask therefore supports automatic temporary file creation and deletion. Temporary files created through KosmicTask are automatically deleted once the parent task has completed.
JavaScript Cocoa powered tasks can create temporary files by calling the KosmicTaskController resultFileWithName function.
function kosmicTask()
{
// form our image file result path
// this file will be automatically deleted when the task ends.
var path = KosmicTaskController.resultFileWithName('capture.png');
// capture screen shot to file
var task = NSTask.launchedTaskWithLaunchPath_arguments('/usr/sbin/screenCapture', ['-t', 'png', path]);
task.waitUntilExit;
// form result dictionary
var result = {kosmicFile: path};
return result
}
Logging and Debugging
Diagnostic and logging information can be written to a task's error stream using the log() function. JavaScript does not feature a native logging capability and the function described here is provided by JSCocoa.
// send log value to stderr
log("Goodbye, kosmos");
NSObject Subclassing
JavaScript Cocoa objects can be subclassed directly from Cocoa's NSObject:
// define the Person class
class Person < NSObject
{
// init method
- (void)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName
{
this.firstName = firstName
this.lastName = lastName
return this
}
// description method
- (NSString *)description
{
return this.firstName + " " + this.lastName
}
}
This is a unique syntax used to define Cocoa objects and closely mirrors objective-C. A similiar syntax is used in Objective-J and JSTalk. Prior to task execution this syntax is converted to valid JavaScript.
Runloop Management
When an JavaScript Cocoa task is run the script runner is transformed into a fully fledged application complete with a run loop (an instance of NSRunLoop). This enables the task to utilise all the features of the Cocoa framework, many of which depend upon the existence of a run loop in order to perform correctly. As a result of its application based nature a task written in JSCocoa will probably take longer to launch and consume more system resources than a regular JavaScript task.
By default however the JSCocoa task will exit its run loop whenever the task entry point exits unless it is requested to do otherwise. This is the case in the example above.
In order for the task to continue executing it is necessary to tell the task controller object (KosmicTaskController ) to keep the task running after the script entry point function has returned. KosmicTaskController is a predefined class that can be accessed by name within the task script .
To keep the task running call the KosmicTaskController keepTaskRunning static method. The task will then continue to process input events on its runloop until the KosmicTaskController stopTask static method is called. The task will then end and return its result to the client.
// define class
class KosmicTask < NSObject
{
// start method
- (void)start
{
var selector = @selector(timerFired:)
this.timer = NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(1, this, selector, nil, true)
this.count = 0
// keep the task running after the entry point function exits
KosmicTaskController.keepTaskRunning
}
// callback method
- (void)timerFired:(NSTimer *)timer
{
this.count++
if (this.count == 5) {
timer.invalidate
KosmicTaskController.stopTask("timer expired " + this.count + " times")
}
}
}
// task entry point
function kosmicTask()
{
// allocate a task object
var task = KosmicTask.instance
// start the task
task.start
}
System Framework Access
JavaScript Cocoa tasks can access system framework classes using the loadFramework function.
// load the AddressBook framework
loadFramework("AddressBook")
function kosmicTask()
{
// access the me object in the shared address book
var person = ABAddressBook.sharedAddressBook.me
// get the first name property
result = person.valueForProperty(kABFirstNameProperty)
return result
}
Syntax Checking
Syntax checking is provided by JSLint which is included as part of JSCocoa.
Note that JSLint will rewrite the syntax used to implement Cocoa class creation. The rewritten code may be referenced in any build error reports.
