JavaScript Cocoa - JSCocoa

KosmicTask Help

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.