- Loading...
Nashorn implements ECMAScript 5.1 specification http://www.ecma-international.org/ecma-262/5.1/
HTML non-normative version of the spec is here: http://es5.github.io/
Nashorn implements number of syntactic and API extensions as well. This page describes syntax and API extensions of nashorn implementation.
This Mozilla JavaScript 1.8 extension is also supported by Nashorn. This syntax allows braces and return keyword to be dropped when defining simple one-liner functions. See also https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/1.8
Example:
function sqr(x) x*x
// is equivalent to
// function sqr(x) { return x*x }
This is another Mozilla JavaScript 1.6 extension supported by Nashorn. ECMAScript for..in iterates over property names or array indices of an object. for..each..in loop iterates over property values of an object rather than property names/indices. See also https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for_each...in
for each (variable in object) { statement }
// print each array element
var arr = [ "hello", "world" ];
for each (a in arr) {
print(a)
}
This is another Rhino extension supported by Nashorn. In a new Constructor(x, y) expression, the last argument can be specified after ")" if it happens to be an object literal. Example:
// This syntax is primarily used to support anonymous class-like syntax for
// Java interface implementation as shown below.
var r = new java.lang.Runnable() {
run: function() { print("run"); }
}
Top-level function statements can be anonymous. Example:
function () {
print("hello")
}
How do you call it then? Say if you had evaluated the above code by "eval" or script engine's "eval" call from Java, you can get the return value to be the function object - which can be invoked later.
Nashorn supports multi-line string literals with Unix shell's here-doc syntax. Example:
var str = <<EOF This is a string that contains multiple lines hello world That's all! EOF print(str)
Expressions can be specified inside string literals with the syntax ${expression}. The string value is computed by substituting value of expressions for ${expression} in the string.
var x = "World"
var str = "Hello, ${x}"
print(str) // prints "Hello, World" because ${x} is substituted with value of variable "x"
Nashorn supports Unix shell like back quote strings. Back quoted strings are evaluated by executing the programs mentioned in the string and returning value produced by the 'exec'-ed program.
// exec "ls -l" to get file listing as a string
var files = `ls -l`
var lines = files.split("\n");
// print only the directories
for (var l in lines) {
var line = lines[l];
if (line.startsWith("d")) // directory
print(line)
}
Like other ECMAScript implementations (like Rhino, v8) Nashorn supports mutable __proto__ magic property to read and write prototype of a given object. See also https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto
__proto__ is deprecated. Please avoid using __proto__. Use Object.getPrototypeOf and Object.setPrototypeOf instead.
ECMAScript specifies Object.getPrototypeOf(obj) http://es5.github.io/#x15.2.3.2 function to get prototype of the given object. This Object.setPrototypeOf is a nashorn specific extension that allows prototype of an object to be set as newProto. Object.setPrototypeOf is one of proposed extensions in ECMAScript 6.
Nashorn implements typed arrays as specified at https://www.khronos.org/registry/typedarray/specs/latest/ For a tutorial presentation, please check out https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays (which includes non-standard StringView which is not implemented by nashorn). Among the typed array constructors, DataView ( https://www.khronos.org/registry/typedarray/specs/latest/#8 ) is not implemented in jdk8's nashorn. DataView is included in jdk8u-dev and so is expected to make it into jdk8u20 release.
Object.bindProperties lets you bind properties of one object to another object. Example:
var obj = {}
var obj2 = { foo: 344 }
// bind properties of 'obj2' to 'obj'
Object.bindProperties(obj, obj2);
print(obj.foo); // obj2.foo
obj.foo = "hello" // obj2.foo assigned
print(obj2.foo); // prints "hello"
// bind to global 'this' is also possible
Object.bindProperties(this, obj2);
print(foo); // prints obj2.foo
foo = 42; // assigns to obj2.foo
print(obj2.foo); // prints 42
The bound object need not be a script object. It could be a Java object as well - usual Java bean style getter/setter properties will be bound. Also a property only with getter will be bound as read-only property.
Nashorn extends ECMAScript Error (or subtype) objects with the following properties.
In addition to this Error.prototype has the following extension functions as well.
Error constructor includes dumpStack() function property
function func() {
throw new Error()
}
function f() {
func()
}
try {
f()
} catch (e) {
print(e.stack)
print(e.lineNumber)
print(e.columnNumber)
print(e.fileName)
}
String.prototype.trimLeft - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/TrimLeft
String.prototype.trimRight - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/TrimRight
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toSource
__FILE__ , __LINE__, __DIR__
Current executing script file, line, directory of the script can be accessed by these global (read-only) properties. This is useful in debug/tracing scripts. __DIR__ can be used like Unix 'dirname' command. Script can load script-file relative path resources using __DIR__.
print(__FILE__, __LINE__, __DIR__)
print function
print function prints it's arguments (after converting those to Strings) on standard output
print("hello", "world")
load function
Loads and evaluates script from a file or a URL or a script object. Examples:
// can load script from files, URLs
load("foo.js"); // loads script from file "foo.js" from current directory
load("http://www.example.com/t.js"); // loads script file from given URL
// loads script from an object's properties.
// Object should have "script" and "name" properties.
// "script" property contains string code of the script.
// "name" property specifies name to be used while reporting errors from script
// This is almost like the standard "eval" except that it associates a name with
// the script string for debugging purpose.
load({ script: "print('hello')", name: "myscript.js"})
// load can also load from pseudo URLs like "nashorn:", "fx:". "nashorn:" pseudo URL scheme
// for nashorn's built-in scripts. "fx:" pseudo URL scheme for JavaFX support scripts
// load nashorn's parser support script - defines 'parse'
// function in global scope
load("nashorn:parser.js");
// load Mozilla compatibility script - which defines global functions
// like importPackage, importClass for rhino compatibility.
load("nashorn:mozilla_compat.js");
loadWithNewGlobal function
loadWithNewGlobal is almost like the function "load" in that it loads script from a file or a URL or a script object. But unlike 'load', loadWithNewGlobal creates a fresh ECMAScript global scope object and loads the script into it. The loaded script's global definitions go into the fresh global scope. Also, the loaded script's modifications of builtin objects (like String.prototype.indexOf) is not reflected in the caller's global scope – these are affected in the newly created global scope.
loadWithNewGlobal({
script: "foo = 333; print(foo)",
name: "test"
});
// prints undefined as "foo" is defined in the new global and not here
print(typeof foo);
exit and quit functions
These synonymous functions exit the current process with specified (optional) exit code.
exit(1); // exit with given exit code exit(); // exit 0 quit(2); // exit with given exit code quit(); // exit 0
Packages, java, javax, javafx, com, edu, org
Packages and related objects are there to support java package, class access from script. The properties of the Packages variable are all the top-level Java packages, such as java and javax etc.
var Vector = Packages.java.util.Vector; // but short-cuts defined for important package prefixes like // Packages.java, Packages.javax, Packages.com // Packages.edu, Packages.javafx, Packages.org var JFrame = javax.swing.JFrame; // javax == Packages.javax var List = java.util.List; // java == Packages.java
jjs> Packages.java [JavaPackage java] jjs> java [JavaPackage java] jjs> java.util.Vector [JavaClass java.util.Vector] jjs> javax [JavaPackage javax] jjs> javax.swing.JFrame [JavaClass javax.swing.JFrame]
JavaImporter constructor
Many times you may want to import many Java packages – but without having to "pollute" global scope. JavaImporter helps in such situations.
// JavaImporter constructor accepts one or more Java Package objects
var imports = new JavaImporter(java.util, java.io);
// a JavaImporter can be used as a "with" expression object
with(imports) {
// classes from java.util and java.io packages can
// can be accessed by unqualified names
var map = new HashMap(); // refers to java.util.HashMap
map.put("js", "javascript");
map.put("java", "java");
map.put("cpp", "c++");
print(map);
var f = new File("."); // refers to java.io.File
print(f.getAbsolutePath());
}
// read text content from the given URL
function readText(url) {
// Using JavaImporter to resolve classes
// from specified java packages within the
// 'with' statement below
with (new JavaImporter(java.io, java.net)) {
// more or less regular java code except for static types
var is = new URL(url).openStream();
try {
var reader = new BufferedReader(
new InputStreamReader(is));
var buf = '', line = null;
while ((line = reader.readLine()) != null) {
buf += line;
}
} finally {
reader.close();
}
return buf;
}
}
print(readText("http://google.com?q=jdk8"))
"Java" global property is a script object that defines useful functions for script-to-Java interface.
Java.type function
Given a name of a Java type, returns an object representing that type in Nashorn. The Java class of the objects used to represent Java types in Nashorn is not Class but rather StaticClass. They are the objects that you can use with the new operator to create new instances of the class as well as to access static members of the class. In Nashorn, Class objects are just regular Java objects that aren't treated specially. Instead of them, StaticClass instances - which we sometimes refer to as "Java type objects" are used as constructors with the new operator, and they expose static fields, properties, and methods. While this might seem confusing at first, it actually closely matches the Java language: you use a different expression (e.g. java.io.File) as an argument in "new" and to address statics, and it is distinct from the Class object (e.g. java.io.File.class). Below we cover in details the properties of the type objects.
var arrayListType = Java.type("java.util.ArrayList")
var intType = Java.type("int")
var stringArrayType = Java.type("java.lang.String[]")
var int2DArrayType = Java.type("int[][]")
// Note that the name of the type is always a string for a fully qualified name. You can // use any of these types to create new instances, e.g.:
var anArrayList = new Java.type("java.util.ArrayList")
// or
var ArrayList = Java.type("java.util.ArrayList")
var anArrayList = new ArrayList
var anArrayListWithSize = new ArrayList(16)
// In the special case of inner classes, you can either use the JVM fully qualified name, // meaning using $ sign in the class name, or you can use the dot:
var ftype = Java.type("java.awt.geom.Arc2D$Float")
// and this works too:
var ftype = Java.type("java.awt.geom.Arc2D.Float")
If the type is abstract, you can instantiate an anonymous subclass of it using an argument list that is applicable to any of its public or protected constructors, but inserting a JavaScript object with functions properties that provide JavaScript implementations of the abstract methods. If method names are overloaded, the JavaScript function will provide implementation for all overloads. E.g.:
var TimerTask = Java.type("java.util.TimerTask")
var task = new TimerTask({ run: function() { print("Hello World!") } })
Nashorn supports a syntactic extension where a "new" expression followed by an argument is identical to invoking the constructor and passing the argument to it, so you can write the above example also as:
var task = new TimerTask {
run: function() {
print("Hello World!")
}
}
which is very similar to Java anonymous inner class definition. On the other hand, if the type is an abstract type with a single abstract method (commonly referred to as a "SAM type") or all abstract methods it has share the same overloaded name), then instead of an object, you can just pass a function, so the above example can become even more simplified to:
var task = new TimerTask(function() { print("Hello World!") })
The use of functions can be taken even further; if you are invoking a Java method that takes a SAM type, you can just pass in a function object, and Nashorn will know what you meant:
var Timer = new (Java.type("java.util.Timer"))
Timer.schedule(function() { print("Hello World!") }, 1000)
java.lang.System.in.read()
Here, Timer.schedule() expects a TimerTask as its argument, so Nashorn creates an instance of a TimerTask subclass and uses the passed function to implement its only abstract method, run(). In this usage though, you can't use non-default constructors; the type must be either an interface, or must have a protected or public no-arg constructor.
Java.extend function
Java.extend function returns a type object for a subclass of the specified Java class (or implementation of the specified interface) that acts as a script-to-Java adapter for it. Note that you can also implement interfaces and subclass abstract classes using new operator on a type object for an interface or abstract class. However, to extend a non-abstract class, you will have to use this method. Example:
var ArrayList = Java.type("java.util.ArrayList")
var ArrayListExtender = Java.extend(ArrayList)
var printSizeInvokedArrayList = new ArrayListExtender() {
size: function() { print("size invoked!"); }
}
var printAddInvokedArrayList = new ArrayListExtender() {
add: function(x, y) {
if(typeof(y) === "undefined") {
print("add(e) invoked!");
} else {
print("add(i, e) invoked!");
}
}
}
Java.from function
Given a Java array or Collection, this function returns a JavaScript array with a shallow copy of its contents. Note that in most cases, you can use Java arrays and lists natively in Nashorn; in cases where for some reason you need to have an actual JavaScript native array (e.g. to work with the array comprehensions functions), you will want to use this method. Example:
var File = Java.type("java.io.File")
var listHomeDir = new File("~").listFiles()
// Java array to JavaScript array conversion by Java.from
var jsListHome = Java.from(listHomeDir)
var jpegModifiedDates = jsListHome
.filter(function(val) { return val.getName().endsWith(".jpg") })
.map(function(val) { return val.lastModified() })
Java.to function
Given a script object and a Java type, converts the script object into the desired Java type. Currently it performs shallow creation of Java arrays, as well as wrapping of objects in Lists and Dequeues. Example:
var anArray = [1, "13", false]
// Java.to used to convert script array to a Java int array
var javaIntArray = Java.to(anArray, "int[]")
print(javaIntArray[0]) // prints 1
print(javaIntArray[1]) // prints 13, as string "13" was converted to number 13
// as per ECMAScript ToNumber conversion
print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0
// as per ECMAScript ToNumber conversion
Java.super function
When given an object created using Java.extend() or equivalent mechanism (that is, any JavaScript-to-Java adapter), returns an object that can be used to invoke superclass methods on that object. E.g.:
var CharArray = Java.type("char[]")
var jString = Java.type("java.lang.String")
var Character = Java.type("java.lang.Character")
function capitalize(s) {
if(s instanceof CharArray) {
return new jString(s).toUpperCase()
}
if(s instanceof jString) {
return s.toUpperCase()
}
return Character.toUpperCase(s) // must be int
}
var sw = new (Java.type("java.io.StringWriter"))
var FilterWriterAdapter = Java.extend(Java.type("java.io.FilterWriter"))
var cw = new FilterWriterAdapter(sw) {
write: function(s, off, len) {
s = capitalize(s)
// Must handle overloads by arity
if(off === undefined) {
cw_super.write(s, 0, s.length())
} else if (typeof s === "string") {
cw_super.write(s, off, len)
}
}
}
var cw_super = Java.super(cw)
cw.write("abcd")
cw.write("e".charAt(0))
cw.write("fgh".toCharArray())
cw.write("**ijk**", 2, 3)
cw.write("***lmno**".toCharArray(), 3, 4)
cw.flush()
print(sw)
Every function is a lambda and a SAM type object
Where ever a JDK8 lambda or SAM (single-abstract-method) type is required, an ECMAScript function can be passed as argument. Nashorn will auto-convert a script function to a lambda object or any SAM interface implementing object.
var IntStream = Java.type("java.util.stream.IntStream");
// IntStream's forEach requires a lambda implementing
// java.util.function.IntConsumer. You can pass a script function!
IntStream.range(0, 100).forEach(
function(x) {
print(x*x)
});
var Thread = Java.type("java.lang.Thread");
// java.lang.Thread constructor requires a java.lang.Runnable
// You can pass script function wherever a SAM is expected
new Thread(function() {
print("I am a thread!");
}).start();
Every lambda is a script function
Any Java object that is an instance of lambda type can be treated like a script function.
var JFunction = Java.type('java.util.function.Function')
var obj = new JFunction() {
apply: function(x) { print(x*x) }
}
// every lambda object is a 'function'
print(typeof obj); // prints "function"
// 'calls' lambda as though it is a function
obj(91);
JSAdapter supports java.lang.reflect.Proxy-like proxy mechanism for script objects.
// A JSAdapter object with proxy-like special hooks
var obj = new JSAdapter() {
__get__: function(name) {
print("getter called for '" + name + "'"); return name;
},
__put__: function(name, value) {
print("setter called for '" + name + "' with " + value);
},
__call__: function(name, arg1, arg2) {
print("method '" + name + "' called with " + arg1 + ", " + arg2);
},
__new__: function(arg1, arg2) {
print("new with " + arg1 + ", " + arg2);
},
__getIds__: function() {
print("__getIds__ called");
return [ "foo", "bar" ];
},
__getValues__: function() {
print("__getValues__ called");
return [ "fooval", "barval" ];
},
__has__: function(name) {ECMAscript typed arrays
print("__has__ called with '" + name + "'");
return name == "js";
},
__delete__: function(name) {
print("__delete__ called with '" + name + "'");
return true;
}
};
// calls __get__
print(obj.foo);
// calls __put__
obj.foo = 33;
// calls __call__
obj.func("hello", "world");
// calls __new__
new obj("hey!", "it works!");
for (i in obj) {
print(i);
}
for each (i in obj) {
print(i);
}
$ARG (-scripting mode only)
This global object can be used to access the arguments passed to the script, similar to how the arguments object is used, for example:
$ jjs -scripting -- arg1 arg2 arg3 jjs> $ARG arg1,arg2,arg3 jjs> $ARG[1] arg2
echo (-scripting mode only)
This is a synonym to "print" function - the values passed in as arguments to be converted to strings, printed to stdout separated by spaces, and followed by a new line.
$ jjs -scripting
jjs> echo("hello world");
hello world
$ENV (-scripting mode only)
$ENV object exposes OS process environment variables to script.
// print $JAVA_HOME and $PATH from the OS shell print($ENV["JAVA_HOME"]) print($ENV["PATH"]) print($ENV.JAVA_HOME) print($ENV.PATH)
$EXEC (-scripting mode only)
This global function launches processes to run commands, for example:
jjs> $EXEC("ls -l")
total 0
drwxr-xr-x+ 1 johndoe staff 4096 Aug 18 11:03 dir
-rwxrw-r-- 1 johndoe staff 168 Aug 19 17:44 file.txt
jjs> $EXEC("cat", "Send this to stdout")
Send this to stdout
If the command does not require any input, you can launch a process using the backtick string notation. For example, instead of $EXEC("ls -l"), you can use `ls -l`.
$OUT (-scripting mode only)
This global object is used to store the latest standard output (stdout) of the process spawned by $EXEC. For example, the result of $EXEC() is saved to $OUT.
$ERR (-scripting mode only)
This global object is used to store the latest standard error (stderr) of the process spawned by $EXEC.
$EXIT (-scripting mode only)
This global object is used to store the exit code of the process spawned by $EXEC. If the exit code is not zero, then the process failed.
var Arrays = Java.type("java.util.Arrays")
// use curl to download JSON weather data from the net
var str = `curl http://api.openweathermap.org/data/2.5/forecast/daily?q=Chennai&mode=json&units=metric&cnt=7`
// parse JSON
var weather = JSON.parse($OUT)
// pull out humidity as array
var humidity = weather.list.map(function(curVal) {
return curVal.humidity
})
// Stream API to print stat
print("Humidity")
print(Arrays["stream(int[])"](humidity).summaryStatistics())
// pull maximum day time temperature
var temp = weather.list.map(function(curVal) {
return curVal.temp.max
})
// Stream API to print stat
print("Max Temperature")
print(Arrays["stream(double[])"](temp).summaryStatistics())
$OPTIONS (-scripting mode only)
This property exposes command line options passed to nashorn "command line".
print("-scripting = " + $OPTIONS._scripting);
print("--compile-only = " + $OPTIONS._compile_only);
print("-timezone = " + $OPTIONS._timezone.ID);
readFully (-scripting mode only)
This function reads the entire contents of a file passed in as a string argument and sends it to stdout, or you can assign the result to a variable.
jjs> readFully("text.txt")
This is the contents of the text.txt file located in the current working directory.
readLine (-scripting mode only)
This function reads one line of input from stdin and sends it to stdout, or you can assign the result to a variable. You can also pass a string to the readLine() function to get a prompt line as in the following example:
jjs> var name = readLine("What is your name? ")
What is your name? Bob
jjs> print("Hello, ${name}!")
Hello, Bob!
jjs>