Go to the first, previous, next, last section, table of contents.


The `js' Program

The `js' program is the JavaScript interpreter command. It can be used to execute JavaScript and JavaScript byte-code files. The progam can also be used to compile JavaScript files into the byte-code files.

Invoking The `js' Program

The js program is invoked as:

js option... file [argument...]

The js program processes the command line options and when the first non-option argument, or the option `--file', is encountered, it is assumed to contain JavaScript or byte-code that should be evaluated. The interpreter will pass all remaining arguments to the script throught the `ARGS' array. The items in the array are strings containing the arguments argument.... The first item of the array is always the name of the script file.

The options can be one or more of the following command line options:

-a
--annotate-assembler
Annotate the created assembler listing with the original JavaScript source code. The option can be used only with the `--assembler' option.
-c
--compile
Compile JavaScript files to byte-code. The generated byte-code is saved to file which name is created from the name of the input file by replacing the suffix `.js' with the suffix `.jsc'. The compilation can be controlled with options `--debug', `--optimize', and `--compiler-option'.
-d type
--dispatch=type
Use the byte-code instruction dispatch method type. The current implementation supports the following dispatch methods:
switch-basic
The basic switch-method using a big switch-case table to dispatch the instruction. This method is available only if the interpreter has been configured with the option `--with-all-dispatchers'.
switch
An optimized version of the switch-method. This method is supported on all environments.
jumps
The fastest dispatch method that uses the `computed goto' statement of the GNU C-compiler. This method is available if the interpreter has been compiler with the GNU C-compiler.
The default dispatch method, for environments that has the GNU C-compiler, is `jumps'. For all other environments, the default method is `switch'.
-e code
--eval=code
Evaluate JavaScript code code.
$ js --eval='System.print ("Hello, world!\n");'
-| Hello, world!
-E
--events
Print the interpreter events to the standard error.
$ js -E -c test.js
[js: garbage collect]
[js: garbage collect]
[js: garbage collect]
[js: garbage collect]
-f
--file
Stop processing options and use the next argument as the name of the JavaScript (or byte-code) file. All the remaining arguments are passed to the interpreter through the ARGS array. The first item of the array will be the name of the script, i.e. the argument that follows the option `--file'.
$ cat hello.js
-| var i;
-| for (i = 0; i < ARGS.length; i++)
-|   System.print (i, ": ", ARGS[i], "\n");
$ js --file hello.js a b c d
-| 0: hello.js
-| 1: a
-| 2: b
-| 3: c
-| 4: d
The option can also be used with the option `--load' to indicate the last file to load. Also in that case, the remaining arguments will be passed to the script through the ARGS array.
-g
--debug
Make the compiler to generate debugging information to the generated byte-code files. This option can be used with the option `--compile'.
-h
--help
Print a short help message that describes the options that can be given to the `js' program.
-l
--load
Load multiple JavaScript and JavaScript byte-code files to the interpreter. Normally, the first non-option argument is evaluated and all remaining arguments are passed to the script as arguments. With the option --load, multiple files can be loaded the to the interpreter. The loading can be stopped with option --file that specifies the last file to load. For example, if we have files `a.js':
function do_a ()
{
  System.print ("do_a()\n");
}
`b.js':
function do_b ()
{
  System.print ("do_b()\n");
}
and `main.js':
do_a ();
do_b ();
the whole application can be run as:
$ js --load a.js b.js --file main.js arguments...
-| do_a()
-| do_b()
-N
--no-compiler
Do not define the compiler to the virtual machine. This option makes the interpreter smaller, but the interpreter can only execute pre-compiled byte-code files. The option disables the `eval' global method.
-O [level]
--optimize[=level]
Set the compiler optimization level to level. The compiler has three different optimization levels:
0
Do not optimize.
1
Perform all cheap optimizations which do not required heavy assembler instruction analyzing.
2
Perform all optimizations, supported by the compiler.
The default optimization level is 1.
-r option
--secure=option
Turn on virtual machine security option option. The following security options are available:
file
Disable insecure methods from the buit-in File object.
system
Disable insecure methods from the buit-in System object.
-s size
--stack-size=size
Set the size of the virtual machine operand stack to size. The size of the virtual machine operand stack is set at the startup-time and it can't be enlarged dynamically at the runtime.
-S
--assembler
Compile JavaScript files to JavaScript assembler. The generated assembler listing is saved to file which name is created from the name of the input file by replacing the suffix `.js' with the suffix `.jas'. The compilation can be controlled with options `--optimize', and `--compiler-option'.
-t
--stacktrace
Print a stack trace on error. When an error occurs during the evaluation of a script, the virtual machine will halt and the `js' program terminates. If the option `--stacktrace' was given to the interpreter, the virtual machine will print a stack trace that shows the call stack at the point of the error. The following listing showns an program that raises an error at the specified recursion level.
function recursive (level)
{
  if (level <= 0)
    error ("recursion limit exceeded");
  else
    recursive (level - 1);
}

recursive (5);
If the program is executed without the `--stacktrace' option, the following result is shown:
$ js hello.js
js: evaluation of file `hello.js' failed:
hello.js:6: recursion limit exceeded
With the `--stacktrace' option, the `js' program will print the following error message:
$ js --stacktrace hello.js
-| VM: error: hello.js:6: recursion limit exceeded
-| VM: stacktrace: stacksize=2048, used=44
-| #0   recursive(): null 1 "recursion limit exceeded"
-| #1   recursive(): null 1 0
-| #2   recursive(): null 1 1
-| #3   recursive(): null 1 2
-| #4   recursive(): null 1 3
-| #5   recursive(): null 1 4
-| #6   .global(): null 1 5
-| js: evaluation of file `hello.js' failed:
-| hello.js:6: recursion limit exceeded
-v
--verbose
Increase the verbosity of the interpreter. The option can be given multiple times to increase the amount of messages the interpreter prints.
-V
--version
Print the version number of the js program.
-W option
--compiler-option=option
Set JavaScript compiler options according to the option specification option. The specification option can be given in two forms. In the normal form, the option specifies a compiler option that should be set on. If the specification option starts with the prefix `no-', the specified option will be turn off. The following option specifications are currently implemented:
all
match most of the compile time options
pedantic
match all compile time options. This option generates as much warnings as possible. It will also complain about some things that are allowed by the ECMAScript standard, but which are consired to show bad programming style, for example, missing semicolons.
runtime
match all runtime options
shadow
warn if a variable declaration shadows a parameter
undefined
runtime check for undefined global variables
unused-argument
warn about unused arguments
unused-variable
warn about unused local variables
with-clobber
warn if the with-lookup of a symbol is clobbered because the symbol is defined to be a local variable or a function argument
missing-semicolon
warn about missing semicolons that are fixed by the missing semicolon inserting during the compilation
strict-ecma
warn about things that are supported by this implementation, but are not allowed by the ECMAScript standard. These features are:
  • line terminators in string and regular expression constants
deprecated
warn if deprecated features has been used in the source code
-x
--executable
Add execute permissions to the generated byte-code files. This option is useful on Linux environments where JavaScript byte-code files can be executed natively with the `binfmt_js' module.
$ cat hello.js
-| System.stdout.writeln ("Hello, world!");
$ js -cx hello.js
$ ./hello.jsc
-| Hello, world!

Evaluating and Executing Code

Compiling JavaScript Code

The compilation of JavaScript code is carried out with the following command:

js [options] -c file...

where file is a JavaScript source file to compile and options specify additional compiler options.

In the simplest form, the compilation goes as follows:

$ js -c hello.js

This example compiles file `hello.js' to byte-code file `hello.jsc' with the default compiler options.

Warning Messages

It is nice to get as many error messages as possible at the compilation time. However, sometimes some error messages are false and it is annoying to see them every time you compile your project. The option --compiler-option can be used to adjust the level of warning messages the compiler generates.

Normally we want to get all possible compiler time warnings. They can be enable with the -Wall option. To set the warnings individually, the following options can be given for the --compiler-option option. The option names can be prefixed with string `no-' to turn them off instead of setting them. For example, let's assume that we want to get as much warnings as possible, but we do not care about unused function arguments:

$ js -Wall -Wno-unused-arguments -c hello.js

In this example, we turn on all warnings `-Wall', but we turn off warnings about unused arguments `-Wno-unused-arguments'.

The js program knows the following warning options:

shadow
Warn if a variable declaration shadows a parameter. For example, when compiling file `test.js' containing code:
function foo (a, b)
{
  var a = 1;
  return a + b;
}
the following warning is generated:
$ js -Wshadow -c test.js
-| test.js:3: warning: declaration of `a' shadows a parameter
unused-argument
Warn if an argument is not used in the function body. For example, when compiling file `test.js' containing code:
function foo (a, b)
{
  return a + 5;
}
the following warning is generated:
$ js -Wunused-argument -c test.js
-| test.js:1: warning: unused argument `b'
unused-variable
Warn if a local variable is not used in the function body. For example, when compiling file `test.js' containing code:
function foo (a, b)
{
  var c;
  return a + b;
}
the following warning is generated:
$ js -Wunused-variable -c test.js
-| test.js:3: warning: unused variable `c'
with-clobber
Warn if the with-lookup of a symbol is clobbered because the symbol is defined to be a local variable or a function argument. For example, when compiling file `test.js' containing code:
function foo (PI)
{
  with (Math)
    System.print ("PI=", PI, "\n");
}
the following warning is generated:
$ js -Wwith-clobber -c test.js
-| test.js:4: warning: the with-lookup of symbol `PI' is
-| clobbered by the argument definition
missing-semicolon
Warn if a semicolon is missing from the input. The missing semicolons are inserted during the parsing by the automatic semicolon inserting. However, since the missing semicolons show bad programming style, this option will warn about them. For example, when compiling file `test.js' containing code:
function foo ()
{
  return 1
}

foo ()
the following warnings are generated:
$ js -Wmissing-semicolon -c test.js
test.js:3: warning: missing semicolon
test.js:6: warning: missing semicolon
strict-ecma
warn about things that are supported by this implementation, but are not allowed by the ECMAScript standard. For example, when compiling file `test.js' containing code:
function foo ()
{
  System.stdout.writeln ("Hello, world!
");
}
the following warning is generated:
$ js -Wstrict-ecma -c test.js
test.js:3: warning: ECMAScript don't allow line terminators in
string constants
deprecated
warn if deprecated features has been used in the source code. For example, when compiling file `test.js' containing code:
function foo ()
{
  for (var i in arguments)
    System.stdout.writeln (i);
}
the following warning is generated:
$ js -Wdeprecated -c test.js
test.js:1: warning: the `arguments' property of Function instance
is deprecated

Besides the compiler time checks, the virtual machine can also perform some checks at the runtime. These checks can be set and unset with the `-Wruntime' option.

The following runtime warnings are supported:

undefined
Warn if the value of an undefined global variable is used. For example, when running file `test.js' containing code:
foo = an_undefined_variable;
the following warning is generated:
$ js test.js
-| VM: warning: using undefined global `an_undefined_variable'

Optimization

Debugging Information

As a default, the JavaScript compiler do not include symbolic debugging information to the generated byte-code files. The debugging information can be generated by giving the compiler -g option. The debugging information is also generated for the internal byte-code files that are created when the interpreter evaluates plain JavaScript source code.

In the current implementation, the debugging information contains only the names of the source files, and mappings from the virtual machine program counter offsets to the source file locations. In the future, it will contain information about local variables and function arguments, so that the symbolic debugger can print their values.

The presence of the debugging information shows in the error messages the interpreter shows. For example, let's consider the following JavaScript source code file `test.js':

function foo (a)
{
  a += 1;
  if (a > 50)
    error ("a overflow");

  return 1;
}

foo (50);

When this file is compiled to the byte-code without debugging information, the following error message is raised:

$ js -c test.js
$ js test.jsc
-| js: evaluation of file `test.jsc' failed:
-| a overflow

If we recompile the file with the debugging information, we will get a more precise error message from the interpreter:

$ js -g -c test.js
$ js test.jsc
-| js: evaluation of file `test.js' failed:
-| test.js:5: a overflow

Now we see the exact source code location where the error occurred.

The debugging information can be removed from the byte-code files after the compilation with the jsdas program.

$ jsdas --strip test.jsc
test.jsc:
jsdas: removing section 3
$ js test.jsc
js: evaluation of file `test.jsc' failed:
a overflow

Assembler Listings

The JavaScript compiler can generate assembler listings from the JavaScript source files. The assembler listings are generated just before the resulting byte-code data would be generated. So the resulting assembler listing is exactly the same that will be in the resulting byte-code data. The assembler listing is generated with the --assembler option. For example, if we have a source file `hello.js' with the following contents:

function hello ()
{
  System.stdout.writeln ("Hello, world!");
  return true;
}

hello ();

it can be compiled to assembler with command

$ js -S hello.js

The command will save the assembler listing in file `hello.jas':

hello:
        load_arg        1
        add_2_i
        min_args        2
        const           "Hello, world!"
        const_i1
        load_global     System
        load_property   stdout
        call_method     writeln
        pop_n           4
        const_true
        return

.global:
        const_i0
        const_null
        jsr             hello
        apop            2

The option --annotate-assembler can be used with the --assembler option. It mixes the original source code to the generated assembler listing. In this format, it is easy to see how different JavaScript constructs are compiled in the assembler. Our example file can be compiled to the annotated assembler with the following command:

$ js -a -S hello.js

The result listing is saved to file `hello.jas':

; -*- asm -*-
; function hello ()

hello:
; {
        load_arg        1
        add_2_i
        min_args        2
;   System.stdout.writeln ("Hello, world!");
        const           "Hello, world!"
        const_i1
        load_global     System
        load_property   stdout
        call_method     writeln
        pop_n           4
;   return true;
        const_true
        return
; }
;
; hello ();

.global:
        const_i0
        const_null
        jsr             hello
        apop            2


Go to the first, previous, next, last section, table of contents.