Installing jshint and rhino for command line javascript analysis

I recently had to install jshint and rhino. It was a bit of a challenge because they needed ant and npm (node package manager). This blog describes what I did and provides a bash shell script that you can use. Jshint (http://www.jshint.com) is a tool that allows you to statically analyze javascript code. It is useful for detecting ertors and enforcing coding standards. Rhino is a command line interpreter for javascript (http://mozilla.org/rhino) that is written in java. It can be used for testing and for server side implementations. You do not have to be root to install these tools.

1 Download

Here are the links to the project code:
ArchiveSizeExtract Command
jsdev.tar.bz24.6Ktar jxf jsdev.tar.bz2
jsdev.tar.gz4.6Ktar zxf jsdev.tar.gz
jsdev.zip6.0Kunzip jsdev.zip

2 Extract

Use the appropriate command from the previous to table to extract the contents of the archive. When you are finished it will look like this:
jsdev/Makefile jsdev/conf/std.conf jsdev/tests/test.sh jsdev/tests/test01.js jsdev/tests/test02.js jsdev/setup.sh

3 Build

Build the system using make. It requires you to have make and java to be installed. When the build it complete, the tools will be in jsdev/rtf/bin directory. You will need to add this directory to your path environment variable as shown in next section to use the tools.

4 Usage

The example below takes you through the entire process of downloading, installing and using the tools.
$ bash -version
$ mkdir /home/me/work
$ cd /home/me/work
$ wget http://downloads.joelinoff.com/jsdev.tar.bz2
<output snipped>
$ tar jxf jsdev.tar.bz2
<output snipped>
$ rm -f jsdev.tar.bz2
$ cd jsdev
$ make
<output snipped>
$ export PATH="/home/me/work/rtf/bin:${PATH}"
$ which jshint
/home/me/work/rtf/bin/jshint
$ which rhino
/home/me/work/rtf/bin/rhino
$ rhino -e 'print("hello, world!");'
hello, world!
$ cat >test.js <<EOF
// Contains intentional errors.

// Missing semi-colon:
var x=42

// Bad conditional expression:
if (x=2) {
    print('GOOD');
}
EOF
$ jshint test.js
/tmp/x.js: line 4, col 9, Missing semicolon.
/tmp/x.js: line 7, col 6, Expected a conditional expression and instead saw an assignment.

2 errors
$ 

5 Trouble Shooting

I have only tested this on a CentOS 5.5 system. If something goes wrong, take a look at the setup.sh script. It is most likely because there are some packages missing. Furthermore, you can remove the sections for ant and/or npm if you already have them installed.

6 Manual Steps

Here are the manual steps.
  1. Install ant.
  2. Install npm (node).
  3. Install jshost using npm.
  4. Install rhino using ant.
  5. Create the rhino tool.
If you want to install in a directory like /usr/local/bin change the rtf variable assignment at line 43.
#!/bin/bash

# Make a complete javascript test environment consisting
# of rhino and jshint.

# ================================================================
# Useful command.
# ================================================================
function docmd() {
    local cmd="$*"
    echo
    echo "# ================================================================"
    echo "# CMD: $cmd"
    echo "# PWD: "`pwd`
    echo "# ================================================================"
    $cmd
    local st=$?
    if (( $st )) ; then
        echo "EXIT: Command exited with status $st (FAILED)."
	echo "      CMD: $cmd"
	exit 1
    else
        echo "EXIT: Command exited with status $st (PASSED)."
    fi
}

# ================================================================
# my-wget
# ================================================================
function my-wget() {
    local src="$1"
    local dst="$2"
    if [ ! -f $dst ] ; then
	docmd wget $src -O $dst
    fi
}

# ================================================================
# Setup
# ================================================================
medir=$(dirname -- $(readlink -f $0))
rootdir=$medir
rtf=$rootdir/rtf
archive=$rootdir/archives
export PATH="${rtf}/bin:${PATH}"
rds=('pkgs' 'rtf' 'archives')
for rd in ${rds[@]} ; do
    if [ ! -d $rd ] ; then
	docmd mkdir $rd
    fi
done

# ================================================================
# ant -- needed for rhino
# ================================================================
fn=apache-ant-1.8.4-bin.tar.bz2
arpath=$archive/$fn 
my-wget http://mirror.nexcess.net/apache/ant/binaries/$fn $arpath

if [ ! -d pkgs/apache-ant-1.8.4 ] ; then
    pushd pkgs
    docmd tar jxf $arpath
    popd
fi

# Very simple install, just copy over the bin and lib dirs.
if [ ! -f $rtf/bin/ant ] ; then
    pushd pkgs
    docmd rsync -avz apache-ant-1.8.4/bin $rtf/
    docmd rsync -avz apache-ant-1.8.4/lib $rtf/
    popd
fi
test -f $rtf/bin/ant

# ================================================================
# node (npm) -- needed for jhint
# ================================================================
fn=node-v0.8.4.tar.gz
arpath=$archive/$fn
my-wget http://nodejs.org/dist/v0.8.4/$fn $arpath

if [ ! -d pkgs/node-v0.8.4 ] ; then
    pushd pkgs
    docmd tar zxf $arpath
    popd
fi

if [ ! -f $rtf/bin/node ] ; then
    pushd pkgs/node-v0.8.4
    docmd ./configure --help
    docmd ./configure --prefix=$rtf
    docmd make
    docmd make install
    popd
fi
test -f $rtf/bin/node

# ================================================================
# jshint
# ================================================================
if [ ! -d pkgs/node-jshint ] ; then
    pushd pkgs
    docmd env GIT_SSL_NO_VERIFY=true git clone https://github.com/jshint/node-jshint.git
    popd
fi

if [ ! -f $rtf/bin/jshint ] ; then
    pushd pkgs/node-jshint
    docmd ./configure --prefix=$rtf
    popd
fi
test -f $rtf/bin/jshint

# ================================================================
# rhino -- javascript interpreter
# ================================================================
if [ ! -d pkgs/rhino ] ; then
    pushd pkgs
    docmd env GIT_SSL_NO_VERIFY=true git clone https://github.com/mozilla/rhino.git
    popd
fi

if [ ! -d rhino/build ] ; then
    pushd pkgs/rhino
    docmd ant
    docmd ant compile-all
    docmd ant jar
    popd
fi

if [ ! -d $rtf/rhino ] ; then
    docmd rsync -avz pkgs/rhino/build $rtf/rhino/
fi

if [ ! -d $rtf/bin/rhino ] ; then
    cat >$rtf/bin/rhino <<EOF
#!/bin/bash

# This should handle spaces in arguments:
#   rhino -e 'print("Hello, world!")''
i=0
argv=()
for arg in "\$@"; do
    argv[\$i]="\$arg"
    i=\$((i + 1))
done

# Now execute the command.
java -jar $rtf/rhino/build/rhino1_7R5pre/js.jar "\${argv[@]}"
EOF
    chmod a+x $rtf/bin/rhino
fi
test -f $rtf/rhino
test -f $rtf/bin/rhino

# ================================================================
# Installation tests.
# ================================================================
if [ ! -f .OK ] ; then
    docmd rhino -e 'print("hello");'
    cat >$$.js <<EOF
print("hello, world");
EOF
    docmd jshint $$.js
    rm -f $$.js
    touch .OK
fi
I hope that this is helpful.

4 thoughts on “Installing jshint and rhino for command line javascript analysis”

  1. Error received is as follows

    # ================================================================
    # CMD: tar jxf /home/administrator/Downloads/Rhino/jsdev/archives/apache-ant-1.8.4-bin.tar.bz2
    # PWD: /home/administrator/Downloads/Rhino/jsdev/pkgs
    # ================================================================

    bzip2: Compressed file ends unexpectedly;
    perhaps it is corrupted? *Possible* reason follows.
    bzip2: Inappropriate ioctl for device
    Input file = (stdin), output file = (stdout)

    It is possible that the compressed file(s) have become corrupted.
    You can use the -tvv option to test integrity of such files.

    You can use the `bzip2recover’ program to attempt to recover
    data from undamaged sections of corrupted files.

    tar: Child returned status 2
    tar: Error is not recoverable: exiting now
    EXIT: Command exited with status 2 (FAILED).
    CMD: tar jxf /home/administrator/Downloads/Rhino/jsdev/archives/apache-ant-1.8.4-bin.tar.bz2
    Command exited with non-zero status 1
    0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 5696maxresident)k
    0inputs+0outputs (0major+2000minor)pagefaults 0swaps
    make: *** [all] Error 1

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.