Skip to content

Instantly share code, notes, and snippets.

@ctkjose
Forked from WebReflection/jsc
Last active March 15, 2024 14:10
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ctkjose/03d14236a55c4b85cb8d6e6156c57b13 to your computer and use it in GitHub Desktop.
Save ctkjose/03d14236a55c4b85cb8d6e6156c57b13 to your computer and use it in GitHub Desktop.
JavaScriptCore for macOS and Linux

JSC

JSC is the JavaScript engine from Apple's JavaScriptCore (WebKit) as a console application that you can use to run script in the terminal.

For more info visit the JSC's webkit wiki page.

Adding a shortcut to JSC

Using jsc is simple, the one issue is that Apple keeps changing the location for jsc. To deal with this issue I just create a symbolic link to the binary:

  1. Find where jsc is at:
find /System/Library/Frameworks/JavaScriptCore.framework -iname jsc

In Catalina and BigSur the above command will return: /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Helpers/jsc.

  1. Add a symbolic link to the jsc binary you located with find:
ln -s /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Helpers/jsc /usr/local/bin

If you already have a symbolic you need to delete it first with: rm /usr/local/bin/jsc.

  1. Now you can just type jsc in the terminal!

Notes using JSC

JSC adds the function print() to write to the terminal.

The function load('[FileName]') lets you load and execute the an external JavaScript file. If the run is successful, it will return the final value of the script.

JSC does not support console.log(), use the function debug() instead.

I usually add a boilerplate for console.log.

var console = {log : debug};

I also have a dump() function to help me debug in JSC. You can include this function by calling load('./util_dump.js').

Old stuff

This is my old shell script, no longer used since it changes so often.

#!/usr/bin/env bash
if [ -f /usr/lib/jsc ]; then
  /usr/lib/jsc "$@"
elif [ -f /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc ]; then
  /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc "$@"
elif [ -f /System/Library/Frameworks/JavaScriptCore.framework/Resources/jsc ]; then
  /System/Library/Frameworks/JavaScriptCore.framework/Resources/jsc "$@"  
fi
function dump(v, prefix, tabs) {
function getTab(tabs){
s = '';
for(var i = 1; i<=tabs; i++) s += ' ';
return s;
};
tabs = (typeof tabs !== 'number') ? 0 : tabs;
var sprefix = getTab(tabs);
var type = '', s ='';
var value = '', i;
var type = typeof v;
function getPrimitive(v, name, tabs){
if(!name) name = 'value';
tabs = (typeof tabs !== 'number') ? 0 : tabs;
var sprefix = getTab(tabs);
var value = '', i;
var type = typeof v;
var s;
switch (type) {
case "number":
value = '' + v.toString() + "\n";
break;
case "boolean":
value = '' + v.toString() + "\n";
break;
case "string":
value = "(" + v.length + '): "' + v + '"' + "\n";
break;
case "function":
value = "<code>\n";
break;
case "object":
//check if null
if (v === null) {
value = "null\n";
//}else if (Array.isArray(v)) {
}else if(Object.prototype.toString.call(v) === '[object Array]'){
value = '(' + v.length + "): [\n";
for (i = 0; i < v.length; i++) {
value += getPrimitive(v[i], i + ':', tabs+1);
}
value += sprefix + "]\n";
}else if (v.nodeName) {
switch (v.nodeType) {
case 1:
value = 'HTMLElement("' + v.nodeName + '")';
break;
case 2:
value = 'ATTRIBUTE_NODE(' + v.nodeName + ')';
break;
case 3:
value = 'TEXT_NODE(' + v.nodeValue + ')';
break;
case 4:
value = 'CDATA_SECTION_NODE(' + v.nodeValue + ')';
break;
case 5:
value = 'ENTITY_REFERENCE_NODE';
break;
case 6:
value = 'ENTITY_NODE';
break;
case 7:
value = 'PROCESSING_INSTRUCTION_NODE(' + v.nodeName + ':' + v.nodeValue + ')';
break;
case 8:
value = 'COMMENT_NODE(' + v.nodeValue + ')';
break;
case 9:
value = 'DOCUMENT_NODE';
break;
case 10:
value = 'DOCUMENT_TYPE_NODE';
break;
case 11:
value = 'DOCUMENT_FRAGMENT_NODE';
break;
case 12:
value = 'NOTATION_NODE';
break;
}
value += "\n";
}else if(v instanceof RegExp){
type = 'RegExp';
value = '/' + v.source + "/\n";
}else if(v instanceof Date){
type = 'Date';
value = '#' + d.toString() + "#\n";
}else{
var keys = Object.keys(v);
value = '(' + keys.length + '): {\n';
s = sprefix + ' ';
for(var prop of keys) {
//debug("prop=" + prop);
var m = v[prop];
value += getPrimitive(m,'"' + prop + '":', tabs+1);
}
value += sprefix + "}\n";
}
break;
default:
value = "unknown\n";
}
return sprefix + name + ' <' + type + '> ' + value;
}
out = getPrimitive(v, prefix, tabs);
if(print){
print(out);
}else if(debug){
debug(out);
}
return out;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment