Skip to content

cobook/jscocoa

Repository files navigation

JSCocoa, a bridge from Javascript to Cocoa

With JSCocoa, you can write Cocoa applications (almost) entirely in Javascript or use it as a Plugin engine (like Acorn and Spice). JSCocoa uses WebKit's Javascript framework, JavascriptCore.

JSCocoa is a way to use Cocoa from Javascript. It works on the Mac (i386, x86_64, PPC), the iPhone and the iPhone simulator. You can write new Cocoa classes in Javascript, replace existing methods of classes by Javascript functions (swizzling them) and call Javascript functions on Cocoa objects (call filter on an NSArray, or use Javascript regular expressions on NSString with myNSString.match(/pattern/)).

JSCocoa can also be used as a replacement for the existing WebKit bridge, letting you use C functions, structs, and calling pretty much anything from your WebView. Access restriction can be setup by JSCocoa's delegate messages (canGetProperty:ofObject:inContext:, canCallMethod:ofObject:argumentCount:arguments:, etc.)

Basically, JSCocoa works like these bridges :

JSCocoa isn't a Javascript framework to use on the Web. For that, check out :

  • Cappuccino an open source framework that makes it easy to build desktop-caliber applications that run in a web browser
  • SproutCore makes building javascript applications fun and easy

Contribute and discuss

  • Discussion group Questions ? Join the Google group and ask away !
  • Twitter Tweet me questions and comments
  • Github fork JSCocoa from Github, add changes, and notify me with a pull request
  • Documentation on Google Code

Who uses it ?

Are you missing on that list ? Send me a mail !

What does it look like ?

Use straight Javascript syntax to call Cocoa.

// Get current application name
var appName = NSWorkspace.sharedWorkspace.activeApplication.NSApplicationName

// Alloc an object (need to release)
var button = NSButton.alloc.initWithFrame(NSMakeRect(0, 0, 100, 40))
// Alloc an object (no need to release)
var button = NSButton.instance({ withFrame:NSMakeRect(0, 0, 100, 40) }) 

// Setting
var window = NSWorkspace.sharedWorkspace.activeApplication.keyWindow
// Instead of calling setTitle ...
window.setTitle('new title')
// ... set the 'title' property
window.title = 'new title'

// Call methods with jQuery-like syntax
obj.call({ withParam1:'Hello', andParam2:'World' }) 
obj['callWithParam1:andParam2:']('Hello', 'World') 
obj.callWithParam1_andParam2('Hello', 'World' )

// Unicode identifiers !
function	追加する(最初の, 次の)	{	return 最初の+ 次の }
var 結果 = 追加する('こんにちは', '世界')
NSApplication.sharedApplication.keyWindow.title = 結果

// Define a new Javascript class usable by Cocoa (inspired by Cappucino)
class MyClass < NSObject
{
	// Custom drawing, calling parent method
	- (void)drawRect:(NSRect)rect
	{
		// do some drawing here
		...
		// Call parent method
		this.Super(arguments)			
	}
	// Class method
	+ (float)addFloatX:(float)x andFloatY:(float)y
	{
		return x + y
	}
}

// Manipulate an existing class
class NSButton
{
	// Add a method to an existing class
	- (void)someNewMethod:(NSString*)name
	{
		...
	}

	// Swizzle an instance method of an existing class
	Swizzle- (void)drawRect:(NSRect)rect
	{
		// Draw something behind the button
		...
		// Call original swizzled method
		this.Original(arguments)
		// Draw something in front of the button
		NSBezierPath.bezierPathWithOvalInRect(rect).stroke
	}
}

Starting up

This will start a controller, eval a file, call a Javascript method and get an ObjC object out of it. You can start multiple interpreters, e.g. one for each document.

// Start
JSCocoa* jsc = [JSCocoa new];

// Eval a file
[jsc evalJSFile:@"path to a file"];
// Eval a string
[jsc evalJSString:@"log(NSWorkspace.sharedWorkspace.activeApplication.NSApplicationName)"];

// Add an object of ours to the Javascript context
[jsc setObject:self withName:@"controller"];

// Call a Javascript method - we can use any object we added with setObject
JSValueRef returnValue = [jsc callJSFunctionNamed:@"myJavascriptFunction" withArguments:self, nil];
// The return value might be a raw Javascript value (null, true, false, a number) or an ObjC object
// To get an ObjC object
id resultingObject = [jsc toObject:returnValue];

// (Cleanup : only needed if you don't use ObjC's Garbage Collection)
[jsc release];

Add it to your project

Going the framework route :

  • Build JSCocoa/JSCocoa.xcodeproj
  • Add built JSCocoa.framework to your project
  • import <JSCocoa/JSCocoa.h>

No framework, adding JSCocoa files into your project :

  • Drag the JSCocoa folder in your project
  • Delete irrelevant files (Info.plist, JSCocoa_Prefix.pch, English.lproj, project files)
  • Add the JavascriptCore framework
  • In 'Build' project settings, add -lffi to 'Other linker flags'
  • import "JSCocoa.h"

Thanks !

  • Gus Mueller — Distant Object code
  • Jonathan 'Wolf' Rentzsch — JRSwizzle

Questions, comments, patches

Send me a mail !

Patrick Geiller
[email protected]

About

Write Cocoa applications in Javascript

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Objective-C 44.5%
  • JavaScript 40.3%
  • C 11.1%
  • Assembly 2.2%
  • C++ 1.9%