A few months ago I started working on a JavaScript to Objective-C bridge. We had already implemented Objective-C in JavaScript, so I figured “why not?”
Well, I never got very far, but thankfully Patrick Geiller apparently had the same idea and actually executed it: He announced JSCocoa today. It looks like it’s a solid bridge, about up to par with PyObjC and RubyCocoa.
While the included GUI interface for trying out JSCocoa is nice, I prefer command line interfaces for my languages, so I ripped out the few lines of code from my original bridge and plugged in JSCocoa.
Code and build instructions on GitHub.
It’s very bare bones at the moment: it will either read one or more file names from the command line arguments, or if no arguments are supplied it will present a no-frills REPL. Obviously line-editing, etc would be one of the next steps, but for now it works nicely with rlwrap.
#import "JSCocoaController.h"
void JSValuePrint(JSContextRef, JSValueRef, JSValueRef *);
int main (int argc, const char * argv[])
{
[[NSAutoreleasePool alloc] init];
id c = [JSCocoaController sharedController];
JSGlobalContextRef ctx = [c ctx];
if (argc > 1)
{
for (int i = 1; i < argc; i++)
[c evalJSFile:[NSString stringWithFormat:@"%s", argv[i]]];
}
else
{
while (1)
{
char buffer[1024];
printf("js> ");
if (fgets(buffer, 1024, stdin) == NULL)
exit(0);
JSStringRef script = JSStringCreateWithUTF8CString(buffer);
JSValueRef exception = NULL;
if (JSCheckScriptSyntax(ctx, script, 0, 0, &exception) && !exception)
{
JSValueRef value = JSEvaluateScript(ctx, script, 0, 0, 0, &exception);
if (exception)
JSValuePrint(ctx, exception, NULL);
if (value && !JSValueIsUndefined(ctx, value))
JSValuePrint(ctx, value, &exception);
}
else
{
printf("Syntax error\n");
}
JSStringRelease(script);
}
}
}
void JSValuePrint(
JSContextRef ctx,
JSValueRef value,
JSValueRef *exception)
{
JSStringRef string = JSValueToStringCopy(ctx, value, exception);
size_t length = JSStringGetLength(string);
char *buffer = malloc(length+1);
JSStringGetUTF8CString(string, buffer, length+1);
JSStringRelease(string);
puts(buffer);
free(buffer);
}