diff options
author | lana <none@none> | 2014-05-14 11:02:04 -0700 |
---|---|---|
committer | lana <none@none> | 2014-05-14 11:02:04 -0700 |
commit | 688e837068c4ee7b04b6d7dfa5a4af2e74d889a3 (patch) | |
tree | ce3a0cb053d6161d41455a7b54ffc4e314210399 | |
parent | c923b9ba16dae0ac455f60d235d0ac99252b1554 (diff) | |
parent | eb896fba1b27a873fa382a99fb0bb17d1fc47735 (diff) |
Mergejdk8u20-b15
93 files changed, 4320 insertions, 250 deletions
diff --git a/samples/BufferArray.java b/samples/BufferArray.java new file mode 100644 index 00000000..00d66023 --- /dev/null +++ b/samples/BufferArray.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import jdk.nashorn.api.scripting.AbstractJSObject; +import java.nio.DoubleBuffer; + +/** + * Simple class demonstrating pluggable script object + * implementation. By implementing jdk.nashorn.api.scripting.JSObject + * (or extending AbstractJSObject which implements it), you + * can supply a friendly script object. Nashorn will call + * 'magic' methods on such a class on 'obj.foo, obj.foo = 33, + * obj.bar()' etc. from script. + * + * In this example, Java nio DoubleBuffer object is wrapped + * as a friendly script object that provides indexed acces + * to buffer content and also support array-like "length" + * readonly property to retrieve buffer's capacity. This class + * also demonstrates a function valued property called "buf". + * On 'buf' method, we return the underlying nio buffer object + * that is being wrapped. + */ +public class BufferArray extends AbstractJSObject { + // underlying nio buffer + private final DoubleBuffer buf; + + public BufferArray(int size) { + buf = DoubleBuffer.allocate(size); + } + + public BufferArray(DoubleBuffer buf) { + this.buf = buf; + } + + // called to check if indexed property exists + @Override + public boolean hasSlot(int index) { + return index > 0 && index < buf.capacity(); + } + + // get the value from that index + @Override + public Object getSlot(int index) { + return buf.get(index); + } + + // set the value at that index + @Override + public void setSlot(int index, Object value) { + buf.put(index, ((Number)value).doubleValue()); + } + + // do you have a property of that given name? + @Override + public boolean hasMember(String name) { + return "length".equals(name) || "buf".equals(name); + } + + // get the value of that named property + @Override + public Object getMember(String name) { + switch (name) { + case "length": + return buf.capacity(); + case "buf": + // return a 'function' value for this property + return new AbstractJSObject() { + @Override + public Object call(Object thiz, Object... args) { + return BufferArray.this.buf; + } + + // yes, I'm a function ! + @Override + public boolean isFunction() { + return true; + } + }; + } + return null; + } +} diff --git a/samples/CastExample.java b/samples/CastExample.java new file mode 100644 index 00000000..d876498d --- /dev/null +++ b/samples/CastExample.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Simple java example with type casts. +// see javacastcounter.js. + +class CastExample { + public final static int I = (int)23.33; + public final String str = (String)"hello"; +} diff --git a/samples/README b/samples/README new file mode 100644 index 00000000..7dc23299 --- /dev/null +++ b/samples/README @@ -0,0 +1 @@ +Simple Nashorn examples that can be run with "jjs" tool. diff --git a/samples/array_mapreduce.js b/samples/array_mapreduce.js new file mode 100644 index 00000000..5335f35d --- /dev/null +++ b/samples/array_mapreduce.js @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Usage: jjs array_mapreduce.js + +// Many Array.prototype functions such as map, +// filter, reduce, reduceRight, every, some are generic. +// These functions accept ECMAScript array as well as +// many array-like objects including java arrays. +// So, you can do map/filter/reduce with Java streams or +// you can also use Array.prototype functions as below. +// See also http://en.wikipedia.org/wiki/MapReduce + +var DoubleArray = Java.type("double[]"); +var StringArray = Java.type("java.lang.String[]"); + +var map = Array.prototype.map; +var filter = Array.prototype.filter; +var reduce = Array.prototype.reduce; + +var jarr = new StringArray(5); +jarr[0] = "nashorn"; +jarr[1] = "ecmascript"; +jarr[2] = "javascript"; +jarr[3] = "js"; +jarr[4] = "scheme"; + +// sum of word lengths +print("Sum word length:", + reduce.call( + map.call(jarr, function(x) x.length), + function(x, y) x + y) +); + +// another array example involving numbers +jarr = new DoubleArray(10); +// make random array of numbers +for (var i = 0; i < jarr.length; i++) + jarr[i] = Math.random(); + +var forEach = Array.prototype.forEach; +// print numbers in the array +forEach.call(jarr, function(x) print(x)); + +// print sum of squares of the random numbers +print("Square sum:", + reduce.call( + map.call(jarr, function(x) x*x), + function(x, y) x + y) +); diff --git a/samples/astviewer.js b/samples/astviewer.js new file mode 100644 index 00000000..090e50ee --- /dev/null +++ b/samples/astviewer.js @@ -0,0 +1,98 @@ +#// Usage: jjs -scripting -fx astviewer.js -- <scriptfile> + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +if (!$OPTIONS._fx) { + print("Usage: jjs -scripting -fx astviewer.js -- <.js file>"); + exit(1); +} + +// Using JavaFX from Nashorn. See also: +// http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/javafx.html + +// This example shows AST of a script file as a JavaFX +// tree view in a window. If no file is specified, AST of +// this script file is shown. This script demonstrates +// 'load' function, JavaFX support by -fx, readFully function +// in scripting mode. + +// JavaFX classes used +var StackPane = Java.type("javafx.scene.layout.StackPane"); +var Scene = Java.type("javafx.scene.Scene"); +var TreeItem = Java.type("javafx.scene.control.TreeItem"); +var TreeView = Java.type("javafx.scene.control.TreeView"); + +// Create a javafx TreeItem to view a AST node +function treeItemForASTNode(ast, name) { + var item = new TreeItem(name); + for (var prop in ast) { + var node = ast[prop]; + if (typeof node == 'object') { + if (node == null) { + // skip nulls + continue; + } + + if (Array.isArray(node) && node.length == 0) { + // skip empty arrays + continue; + } + + var subitem = treeItemForASTNode(node, prop); + } else { + var subitem = new TreeItem(prop + ": " + node); + } + item.children.add(subitem); + } + return item; +} + +// do we have a script file passed? if not, use current script +var sourceName = arguments.length == 0? __FILE__ : arguments[0]; + +// load parser.js from nashorn resources +load("nashorn:parser.js"); + +// read the full content of the file and parse it +// to get AST of the script specified +var ast = parse(readFully(sourceName)); + +// JavaFX start method +function start(stage) { + stage.title = "AST Viewer"; + var rootItem = treeItemForASTNode(ast, sourceName); + var tree = new TreeView(rootItem); + var root = new StackPane(); + root.children.add(tree); + stage.scene = new Scene(root, 300, 450); + stage.show(); +} diff --git a/samples/barchart_weather.js b/samples/barchart_weather.js new file mode 100644 index 00000000..8574f0a2 --- /dev/null +++ b/samples/barchart_weather.js @@ -0,0 +1,116 @@ +#// Usage: jjs -fx barchart_weather.js + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Example that retrieves weather data from a URL in JSON +// format and draws bar chart using JavaFX + +// -fx check +if (! $OPTIONS._fx) { + print("Usage: jjs -fx barchart_weather.js"); + exit(1); +} + +// Java classes used +var URL = Java.type("java.net.URL"); +var BufferedReader = Java.type("java.io.BufferedReader"); +var InputStreamReader = Java.type("java.io.InputStreamReader"); + +// function to retrieve text content of the given URL +function readTextFromURL(url) { + var str = ''; + var u = new URL(url); + var reader = new BufferedReader( + new InputStreamReader(u.openStream())); + try { + reader.lines().forEach(function(x) str += x); + return str; + } finally { + reader.close(); + } +} + +// change URL for your city here! +var url = "http://api.openweathermap.org/data/2.5/forecast?q=chennai,india&units=metric&mode=json"; + +// download JSON document and parse +var json = readTextFromURL(url); +var weather = JSON.parse(json); + +// View JSON of this using site such as http://www.jsoneditoronline.org/ to know +// about the JSON data format used by this site + +// Extracted data from the json object +var temp = weather.list.map(function(x) x.main.temp); +var temp_min = weather.list.map(function(x) x.main.temp_min); +var temp_max = weather.list.map(function(x) x.main.temp_max); +var date = weather.list.map(function(x) x.dt_txt); + +// JavaFX classes used +var Scene = Java.type("javafx.scene.Scene"); +var BarChart = Java.type("javafx.scene.chart.BarChart"); +var CategoryAxis = Java.type("javafx.scene.chart.CategoryAxis"); +var NumberAxis = Java.type("javafx.scene.chart.NumberAxis"); +var XYChart = Java.type("javafx.scene.chart.XYChart"); + +function start(stage) { + stage.title="Chennai Weather Bar Chart"; + var xAxis = new CategoryAxis(); + xAxis.label = "date/time"; + var yAxis = new NumberAxis(); + yAxis.label = "temp in C"; + var bc = new BarChart(xAxis, yAxis); + + // 3 bars per datetime item - temp, min temp and max temp + var s1 = new XYChart.Series(); + s1.name = "temp"; + for (d in date) { + s1.data.add(new XYChart.Data(date[d], temp[d])); + } + + var s2 = new XYChart.Series(); + s2.name = "min temp"; + for (d in date) { + s2.data.add(new XYChart.Data(date[d], temp_min[d])); + } + + var s3 = new XYChart.Series(); + s3.name = "max temp"; + for (d in date) { + s3.data.add(new XYChart.Data(date[d], temp_max[d])); + } + + bc.data.addAll(s1, s2, s3); + + stage.scene = new Scene(bc, 800, 600); + stage.show(); +} diff --git a/samples/call_lambda.js b/samples/call_lambda.js new file mode 100644 index 00000000..d865164f --- /dev/null +++ b/samples/call_lambda.js @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// nashorn allows you treat every Java8 lambda as a function + +var JFunction = Java.type("java.util.function.Function"); +var obj = new JFunction() { + apply: function(x) { + print(x + ", lambda"); + } +}; + +// prints 'function' +print(typeof obj); + +// call it! +obj("hello"); diff --git a/samples/counters.js b/samples/counters.js index 226ec3de..d89ad581 100644 --- a/samples/counters.js +++ b/samples/counters.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,7 +33,11 @@ * This file can be run along with any script you want to run * to print aggregate stat counters from nashorn. * - * Usage: jjs <your-file.js> counters.js + * Usage: jjs -J-Dnashorn.debug <your-file.js> counters.js */ -Debug.dumpCounters(); +if (java.lang.System.getProperty("nashorn.debug") == null) { + print("Usage: jjs -J-Dnashorn.debug <your-file.js> counters.js"); +} else { + Debug.dumpCounters(); +} diff --git a/samples/dirname.js b/samples/dirname.js new file mode 100644 index 00000000..119d4f33 --- /dev/null +++ b/samples/dirname.js @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// __DIR__ variable is equivalent of `dirname $0` in +// shell scripts - expands to the directory where +// the current script is located. + +print("This script is in the directory: " + __DIR__); diff --git a/samples/disassemble.js b/samples/disassemble.js new file mode 100644 index 00000000..654b9dd8 --- /dev/null +++ b/samples/disassemble.js @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Usage: jjs disassemble.js -- <.class-file-path> + +// Simple .class disassembler that uses bundled ObjectWeb ASM +// classes in jdk8. WARNING: Bundled ObjectWeb ASM classes are +// not part of official jdk8 API. It can be changed/removed +// without notice. So, this script is brittle by design! + +// This example demonstrates passing arguments to script +// from jjs command line, nio and ASM usage. + +// classes used +var FileSystems = Java.type("java.nio.file.FileSystems"); +var Files = Java.type("java.nio.file.Files"); +var System = Java.type("java.lang.System"); +var PrintWriter = Java.type("java.io.PrintWriter"); + +// WARNING: uses non-API classes of jdk8! +var ClassReader = Java.type("jdk.internal.org.objectweb.asm.ClassReader"); +var TraceClassVisitor = Java.type("jdk.internal.org.objectweb.asm.util.TraceClassVisitor"); + +// convert file name to Path instance +function path(file) { + return FileSystems.default.getPath(file); +} + +// read all file content as a byte[] +function readAllBytes(file) { + return Files.readAllBytes(path(file)); +} + +// disassemble .class byte[] and prints output to stdout +function disassemble(bytecode) { + var pw = new PrintWriter(System.out); + new ClassReader(bytecode).accept(new TraceClassVisitor(pw), 0); +} + +// check for command line arg (for .class file name) +if (arguments.length == 0 || !arguments[0].endsWith('.class')) { + print("Usage: jjs disassemble -- <.class file>"); + exit(1); +} + +// disassemble the given .class file +disassemble(readAllBytes(arguments[0])); diff --git a/samples/engine/README b/samples/engine/README new file mode 100644 index 00000000..88584955 --- /dev/null +++ b/samples/engine/README @@ -0,0 +1 @@ +Using javax.script engine API of nashorn from script! diff --git a/samples/engine/accessvar.js b/samples/engine/accessvar.js new file mode 100644 index 00000000..ae9ec7de --- /dev/null +++ b/samples/engine/accessvar.js @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Simple example showing global variable access from caller + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// eval code! +engine.eval("x = 'hello'"); + +// access global var from engine +print(engine.get('x')); diff --git a/samples/engine/callfunc.js b/samples/engine/callfunc.js new file mode 100644 index 00000000..76108fd1 --- /dev/null +++ b/samples/engine/callfunc.js @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// simple example showing how to call a global script +// function from caller + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// eval code! +engine.eval("function func(name) { print('I am func, hello ' + name) }"); + +// invoke functions, methods of code evaluated by engine +// from javax.script.Invocable interface. But, hey, +// calling code is JavaScript and don't worry about types :) + +engine.invokeFunction("func", "Nashorn"); diff --git a/samples/engine/callmethod.js b/samples/engine/callmethod.js new file mode 100644 index 00000000..8199dcd6 --- /dev/null +++ b/samples/engine/callmethod.js @@ -0,0 +1,64 @@ +#// Usage: jjs -scripting callmethod.js + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// simple example demonstrating calling a script object +// method from script engine user code + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// eval code - too many script escapes? +// use heredoc ! +engine.eval(<<CODE + var obj = { + func: function() { + print("I am func of " + this); + }, + + toString: function() { + return "Object 'obj'"; + } + }; +CODE); + +// invoke methods of an object in script world +// from javax.script.Invocable interface. But, hey, +// calling code is JavaScript and don't worry about types :) + +// get that script object on which to call a method +var scriptObj = engine.get("obj"); +// call 'func' method on object 'obj' +engine.invokeMethod(scriptObj, "func"); diff --git a/samples/engine/exposevar.js b/samples/engine/exposevar.js new file mode 100644 index 00000000..93f57ed8 --- /dev/null +++ b/samples/engine/exposevar.js @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Example showing how to expose a script global var from caller + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// expose variable to engine +engine.put("name", "Nashorn"); + +// access it from script +engine.eval("print('Hello, ' + name)"); diff --git a/samples/engine/foreignobject.js b/samples/engine/foreignobject.js new file mode 100644 index 00000000..3850089d --- /dev/null +++ b/samples/engine/foreignobject.js @@ -0,0 +1,71 @@ +#// Usage: jjs -scripting foreignobject.js + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// cross nashorn engine scripting +// access script objects from other engines in natural syntax + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// eval code! +engine.eval(<<CODE + var obj = { + foo: 42, + func: function() { + print("func: " + this.foo); + } + }; +CODE); + +// Nashorn engine returns script objects as instance of +// the class jdk.nashorn.api.scripting.ScriptObjectMirror +// But nashorn's dynalink linker can treat these objects +// specially to support natural script syntax to access.. +// In Java code, you need to use ScriptObjectMirror's +// methods though. Once again, script world is simpler :-) + +var foreignObj = engine.get("obj"); +// access properties, functions of it +// with natural syntax +print(foreignObj.foo); +foreignObj.func(); +print(typeof foreignObj.func); + +// access engine's global +var foreignGlobal = engine.eval("this"); +// create objects in engine's world from here! +print(new foreignGlobal.Object()); +print(new foreignGlobal.Date()); diff --git a/samples/engine/hello.js b/samples/engine/hello.js new file mode 100644 index 00000000..37fabbfe --- /dev/null +++ b/samples/engine/hello.js @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Simple hello world example showing create engine +// and eval simple script + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); +// eval code! +engine.eval("print('hello world')"); diff --git a/samples/engine/interface.js b/samples/engine/interface.js new file mode 100644 index 00000000..75b7aa21 --- /dev/null +++ b/samples/engine/interface.js @@ -0,0 +1,60 @@ +#// Usage: jjs -scripting interface.js + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Example demonstrating how to implement a Java interface +// whose methods are backed by global script functions + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// eval code - too many script escapes? +// use heredoc ! +engine.eval(<<CODE +function run() { + print("run global function called"); +} +CODE); + +// create Java interface object whose methods are +// implemented by script functions. This is from +// javax.script.Invocable. But we are in JS world, +// don't worry about types :) + +var Runnable = Java.type("java.lang.Runnable"); +var r = engine.getInterface(Runnable.class); +print(r.class); + +r.run(); diff --git a/samples/engine/interface2.js b/samples/engine/interface2.js new file mode 100644 index 00000000..771b1101 --- /dev/null +++ b/samples/engine/interface2.js @@ -0,0 +1,63 @@ +#// Usage: jjs -scripting interface2.js + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Simple example demonstrating how to implement java interface +// whose methods are backed by script methods of a script object + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// eval code - too many script escapes? +// use heredoc ! +engine.eval(<<CODE + var obj = { + run: function() { + print("I am run method of 'obj'"); + } + }; +CODE); + +// create Java interface object whose methods are +// implemented by script methods of a script object +// This is from javax.script.Invocable. But we are +// in JS world, don't worry about types :) + +var Runnable = Java.type("java.lang.Runnable"); + +var scriptObj = engine.get("obj"); +var r = engine.getInterface(scriptObj, Runnable.class); +print(r.class); +r.run(); diff --git a/samples/engine/lambda_as_func.js b/samples/engine/lambda_as_func.js new file mode 100644 index 00000000..2600f17a --- /dev/null +++ b/samples/engine/lambda_as_func.js @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Simple example demonstrating how to expose 'function's +// from embedding code. Any lambda object exposed to engine +// can be called as 'function' in script. + +var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); +// create manager +var manager = new ScriptEngineManager(); +// create engine +var engine = manager.getEngineByName("js"); + +// Any lambda (@FunctionalInterface annotated type) object can be +// be exposed from script embedding code. Script can call +// it as a function +engine.put("upper", new java.util.function.Function() { + apply: function(x) x.toUpperCase() +}); + +print(engine.eval("upper('hello')")); diff --git a/samples/env.js b/samples/env.js new file mode 100644 index 00000000..74377ebd --- /dev/null +++ b/samples/env.js @@ -0,0 +1,43 @@ +#// Usage: jjs -scripting env.js + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// In nashorn -scripting mode, +// "$ENV" object exposes process +// environment variables + +print($ENV.PATH); +print($ENV.JAVA_HOME); + +for (i in $ENV) { + print(i, "->", $ENV[i]); +} diff --git a/samples/expression_closure.js b/samples/expression_closure.js new file mode 100644 index 00000000..1efb1842 --- /dev/null +++ b/samples/expression_closure.js @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// nashorn supports expression closures extension of +// Mozilla JavaScript 1.8. See also +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/1.8 + +// leave {, } and 'return' keyword + +function sqr(x) x*x; + +// prints 289 (= 17*17) +print(sqr(17)); diff --git a/samples/fileline.js b/samples/fileline.js new file mode 100644 index 00000000..05c99759 --- /dev/null +++ b/samples/fileline.js @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// nashorn supports pseudo global variables __FILE__ +// and __LINE__ that expands to currently executed +// script file name and current script line number + +// prints current file and line number +print("executing " + __FILE__ + " @ " + __LINE__); diff --git a/samples/fizzbuzz.js b/samples/fizzbuzz.js new file mode 100644 index 00000000..ba8d83d4 --- /dev/null +++ b/samples/fizzbuzz.js @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// What is FizzBuzz? http://c2.com/cgi/wiki?FizzBuzzTest + +// Yet another FizzBuzz impl. using Java 8 lambda and stream +// but using Nashorn. This is ECMAScript port of @stuartmarks' +// Java implementation + +var IntStream = Java.type("java.util.stream.IntStream"); + +function ifmod(m, r, f) { + return function(i) { return i % m == 0? r : f(i); } +} + +// pass script function for lambda +IntStream.rangeClosed(1, 100). + mapToObj( + ifmod(15, "FizzBuzz", ifmod(5, "Buzz", ifmod(3, "Fizz", String)))) + .forEach(print); diff --git a/samples/for_each.js b/samples/for_each.js new file mode 100644 index 00000000..10fc39a1 --- /dev/null +++ b/samples/for_each.js @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// nashorn supports for..each extension supported +// by Mozilla. See also +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for_each...in + +var strs = [ "hello", "world" ]; +for each (str in strs) + print(str); + +// create a java int[] object +var JArray = Java.type("int[]"); +var arr = new JArray(10); + +// store squares as values +for (i in arr) + arr[i] = i*i; + +// for .. each on java arrays +print("squares"); +for each (i in arr) + print(i); + +var System = Java.type("java.lang.System"); + +// for..each on java Iterables +// print System properties as name = value pairs +print("System properties"); +for each (p in System.properties.entrySet()) { + print(p.key, "=", p.value); +} + +// print process environment vars as name = value pairs +print("Process environment"); +for each (e in System.env.entrySet()) { + print(e.key, "=", e.value); +} diff --git a/samples/gaussian_random.js b/samples/gaussian_random.js new file mode 100644 index 00000000..f52f49f3 --- /dev/null +++ b/samples/gaussian_random.js @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// print 100 Guassian distributed numbers + +var Random = Java.type("java.util.Random"); +var DoubleStream = Java.type("java.util.stream.DoubleStream"); + +var r = new Random(); + +// expression closure (see expression_closure.js as well) +// passed as lambda double generator. "print" passed as +// double consumer lambda to 'forEach' method. + +DoubleStream + .generate(function() r.nextGaussian()) + .limit(100) + .forEach(print); diff --git a/samples/gaussian_random_bind.js b/samples/gaussian_random_bind.js new file mode 100644 index 00000000..052520cd --- /dev/null +++ b/samples/gaussian_random_bind.js @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// print 100 Guassian distributed numbers + +var Random = Java.type("java.util.Random"); +var DoubleStream = Java.type("java.util.stream.DoubleStream"); + +// function as lambda double generator. "print" passed as +// double consumer lambda to 'forEach' method. +// Function.prototype.bind used to attach 'state' for the +// generator function. + +DoubleStream + .generate( + function(r) { + return r.nextGaussian() + }.bind(this, new Random())) + .limit(100) + .forEach(print); diff --git a/samples/gutenberg.js b/samples/gutenberg.js new file mode 100644 index 00000000..4d83a573 --- /dev/null +++ b/samples/gutenberg.js @@ -0,0 +1,142 @@ +#// Usage: jjs -scripting gutenberg.js + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Simple example that demonstrates reading XML Rss feed +// to generate a HTML file from script and show it by browser + +// Java classes used +var Characters = Java.type("javax.xml.stream.events.Characters"); +var Factory = Java.type("javax.xml.stream.XMLInputFactory"); +var File = Java.type("java.io.File"); +var FileWriter = Java.type("java.io.FileWriter"); +var PrintWriter = Java.type("java.io.PrintWriter"); +var URL = Java.type("java.net.URL"); + +// read Rss feed from a URL. Returns an array +// of objects having only title and link properties +function readRssFeed(url) { + var fac = Factory.newInstance(); + var reader = fac.createXMLEventReader(url.openStream()); + + // get text content from next event + function getChars() { + var result = ""; + var e = reader.nextEvent(); + if (e instanceof Characters) { + result = e.getData(); + } + return result; + } + + var items = []; + var title, link; + var inItem = false; + while (reader.hasNext()) { + var evt = reader.nextEvent(); + if (evt.isStartElement()) { + var local = evt.name.localPart; + if (local == "item") { + // capture title, description now + inItem = true; + } + + if (inItem) { + switch (local) { + case 'title': + title = getChars(); + break; + case 'link': + link = getChars(); + break; + } + } + } else if (evt.isEndElement()) { + var local = evt.name.localPart; + if (local == "item") { + // one item done, save it in result array + items.push({ title: title, link: link }); + inItem = false; + } + } + } + + return items; +} + +// generate simple HTML for an RSS feed +function getBooksHtml() { + var url = new URL("http://www.gutenberg.org/cache/epub/feeds/today.rss"); + var items = readRssFeed(url); + + var str = "<ul>"; + + // Nashorn's string interpolation and heredoc + // support is very handy in generating text content + // that is filled with elements from runtime objects. + // We insert title and link in <li> elements here. + for each (i in items) { + str += <<EOF +<li> + <a href="${i.link}">${i.title}</a> +</li> +EOF + } + str += "</ul>"; + return str; +} + +// write the string to the given file +function writeTo(file, str) { + var w = new PrintWriter(new FileWriter(file)); + try { + w.print(str); + } finally { + w.close(); + } +} + +// generate books HTML +var str = getBooksHtml(); + +// write to file. __DIR__ is directory where +// this script is stored. +var file = new File(__DIR__ + "books.html"); +writeTo(file, str); + +// show it by desktop browser +try { + var Desktop = Java.type("java.awt.Desktop"); + Desktop.desktop.browse(file.toURI()); +} catch (e) { + print(e); +} diff --git a/samples/heredoc.js b/samples/heredoc.js new file mode 100644 index 00000000..0c52ca93 --- /dev/null +++ b/samples/heredoc.js @@ -0,0 +1,51 @@ +#// Usage: jjs -scripting heredoc.js + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Nashorn supports Shell script like here-documents +// in -scripting mode. Here-docs are multi-line strings +// that are possibly interpolated with ${} expressions +// See also http://en.wikipedia.org/wiki/Here_document + +var sender = "Buffy the Vampire Slayer"; +var recipient = "Spike"; + +print(<<END + +Dear ${recipient}, + +I wish you to leave Sunnydale and never return. + +Not Quite Love, +${sender} + +END); diff --git a/samples/interface_impl.js b/samples/interface_impl.js new file mode 100644 index 00000000..5e498166 --- /dev/null +++ b/samples/interface_impl.js @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// nashorn supports Java interface implementation +// by script using anonymous class-like syntax + +var Runnable = Java.type("java.lang.Runnable"); +var Thread = Java.type("java.lang.Thread"); +// use anonymous class-like new syntax +var r = new Runnable() { + run: function() { + print("I am a runnable " + Thread.currentThread()); + } +} + +r.run(); + +var t = new Thread(r); +t.start(); +t.join(); diff --git a/samples/javaastviewer.js b/samples/javaastviewer.js new file mode 100644 index 00000000..c446abe5 --- /dev/null +++ b/samples/javaastviewer.js @@ -0,0 +1,202 @@ +#// Usage: jjs -fx javaastviewer.js -- <.java files> + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This example demonstrates Java subclassing by Java.extend +// and javac Compiler and Tree API. This example also uses +// -fx and javafx TreeView to visualize Java AST as TreeView + +if (!$OPTIONS._fx || arguments.length == 0) { + print("Usage: jjs -fx javaastviewer.js -- <.java files>"); + exit(1); +} + +// Java types used +var Enum = Java.type("java.lang.Enum"); +var HashSet = Java.type("java.util.HashSet"); +var Name = Java.type("javax.lang.model.element.Name"); +var List = Java.type("java.util.List"); +var Set = Java.type("java.util.Set"); +var SimpleTreeVisitor = Java.type("com.sun.source.util.SimpleTreeVisitor"); +var StringArray = Java.type("java.lang.String[]"); +var ToolProvider = Java.type("javax.tools.ToolProvider"); +var Tree = Java.type("com.sun.source.tree.Tree"); + +function javaASTToScriptObject(args) { + // properties ignored (javac implementation class properties) in AST view. + // may not be exhaustive - any getAbc would become "abc" property or + // public field becomes a property of same name. + var ignoredProps = new HashSet(); + for each (var word in + ['extending', 'implementing', 'init', 'mods', 'clazz', 'defs', + 'expr', 'tag', 'preferredPosition', 'qualid', 'recvparam', + 'restype', 'params', 'startPosition', 'thrown', + 'tree', 'typarams', 'typetag', 'vartype']) { + ignoredProps.add(word); + } + + // get the system compiler tool + var compiler = ToolProvider.systemJavaCompiler; + + // get standard file manager + var fileMgr = compiler.getStandardFileManager(null, null, null); + + // make a list of compilation unit from command line argument file names + // Using Java.to convert script array (arguments) to a Java String[] + var compUnits = fileMgr.getJavaFileObjects(Java.to(args, StringArray)); + + // create a new compilation task + var task = compiler.getTask(null, fileMgr, null, null, null, compUnits); + + // subclass SimpleTreeVisitor - converts Java AST node to + // a simple script object by walking through it + var ConverterVisitor = Java.extend(SimpleTreeVisitor); + + var visitor = new ConverterVisitor() { + // convert java AST node to a friendly script object + // which can be viewed. Every node ends up in defaultAction + // method of SimpleTreeVisitor method. + + defaultAction: function (node, p) { + var resultObj = {}; + // Nashorn does not iterate properties and methods of Java objects + // But, we can bind properties of any object (including java objects) + // to a script object and iterate it! + var obj = {}; + Object.bindProperties(obj, node); + + // we don't want every property, method of java object + for (var prop in obj) { + var val = obj[prop]; + var type = typeof val; + // ignore 'method' members + if (type == 'function' || type == 'undefined') { + continue; + } + + // ignore properties from Javac implementation + // classes - hack by name!! + if (ignoredProps.contains(prop)) { + continue; + } + + // subtree - recurse it + if (val instanceof Tree) { + resultObj[prop] = visitor.visit(val, p); + } else if (val instanceof List) { + // List of trees - recurse each and make an array + var len = val.size(); + if (len != 0) { + var arr = []; + for (var j = 0; j < len; j++) { + var e = val[j]; + if (e instanceof Tree) { + arr.push(visitor.visit(e, p)); + } + } + resultObj[prop] = arr; + } + } else if (val instanceof Set) { + // Set - used for modifier flags + // make array + var len = val.size(); + if (len != 0) { + var arr = []; + for each (var e in val) { + if (e instanceof Enum || typeof e == 'string') { + arr.push(e.toString()); + } + } + resultObj[prop] = arr; + } + } else if (val instanceof Enum || val instanceof Name) { + // make string for any Enum or Name + resultObj[prop] = val.toString(); + } else if (type != 'object') { + // primitives 'as is' + resultObj[prop] = val; + } + } + return resultObj; + } + } + + // top level object with one property for each compilation unit + var scriptObj = {}; + for each (var cu in task.parse()) { + scriptObj[cu.sourceFile.name] = cu.accept(visitor, null); + } + + return scriptObj; +} + +// JavaFX classes used +var StackPane = Java.type("javafx.scene.layout.StackPane"); +var Scene = Java.type("javafx.scene.Scene"); +var TreeItem = Java.type("javafx.scene.control.TreeItem"); +var TreeView = Java.type("javafx.scene.control.TreeView"); + +// Create a javafx TreeItem to view a script object +function treeItemForObject(obj, name) { + var item = new TreeItem(name); + for (var prop in obj) { + var node = obj[prop]; + if (typeof node == 'object') { + if (node == null) { + // skip nulls + continue; + } + var subitem = treeItemForObject(node, prop); + } else { + var subitem = new TreeItem(prop + ": " + node); + } + item.children.add(subitem); + } + + item.expanded = true; + return item; +} + +var commandArgs = arguments; + +// JavaFX start method +function start(stage) { + var obj = javaASTToScriptObject(commandArgs); + stage.title = "Java AST Viewer" + var rootItem = treeItemForObject(obj, "AST"); + rootItem.expanded = true; + var tree = new TreeView(rootItem); + var root = new StackPane(); + root.children.add(tree); + stage.scene = new Scene(root, 300, 450); + stage.show(); +} diff --git a/samples/javacastcounter.js b/samples/javacastcounter.js new file mode 100644 index 00000000..607b2f82 --- /dev/null +++ b/samples/javacastcounter.js @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Usage: jjs javacastcounter.js -- <.java files> + +// This example demonstrates Nashorn Java.extend API +// to subclass a Java class from script. + +// This example uses Javac Compiler and Tree API +// to list type casts used in java source files. + +if (arguments.length == 0) { + print("Usage: jjs javacastcounter.js -- <.java files>"); + exit(1); +} + +// Java types used +var ToolProvider = Java.type("javax.tools.ToolProvider"); +var TreeScanner = Java.type("com.sun.source.util.TreeScanner"); +var Trees = Java.type("com.sun.source.util.Trees"); +var StringArray = Java.type("java.lang.String[]"); + +// get the system compiler tool +var compiler = ToolProvider.systemJavaCompiler; + +// get standard file manager +var fileMgr = compiler.getStandardFileManager(null, null, null); + +// make a list of compilation unit from command line argument file names +// Using Java.to convert script array (arguments) to a Java String[] +var compUnits = fileMgr.getJavaFileObjects(Java.to(arguments, StringArray)); + +// create a new compilation task +var task = compiler.getTask(null, fileMgr, null, null, null, compUnits); + +// SourcePositions object to get positions of AST nodes +var sourcePositions = Trees.instance(task).sourcePositions; + +// Subclass TreeScanner class +var CastCounter = Java.extend(TreeScanner); + +var counter = new CastCounter() { + // current CompilationUnitTree + compUnit: null, + // current LineMap (pos -> line, column) + lineMap: null, + // current compilation unit's file name + fileName: null, + + // overrides of TreeScanner methods + + visitCompilationUnit: function(node, p) { + // capture info about current Compilation unit + this.compUnit = node; + this.lineMap = node.lineMap; + this.fileName = node.sourceFile.name; + + // Using Java.super API to call super class method here + return Java.super(counter).visitCompilationUnit(node, p); + }, + + visitTypeCast: function(node, p) { + // print information on this type cast node + var pos = sourcePositions.getStartPosition(this.compUnit, node); + var line = this.lineMap.getLineNumber(pos); + var col = this.lineMap.getColumnNumber(pos); + print(node + " @ " + this.fileName + ":" + line + ":" + col); + + // count one more type cast + return 1; + }, + + reduce: function(r1, r2) { + return (r1 == null ? 0 : r1) + (r2 == null ? 0 : r2); + } +}; + +// print total number of type cast nodes seen +print("Total casts:", counter.scan(task.parse(), null)); diff --git a/samples/javaimporter.js b/samples/javaimporter.js new file mode 100644 index 00000000..dd487ec1 --- /dev/null +++ b/samples/javaimporter.js @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// JavaImporter along with 'with' statement helps in +// localized Java class references + +function readTextFromURL(url) { + + // equivalent to + // + // import java.io.*; + // import java.net.*; + // import java.lang.StringBuffer; + // + // only inside the 'with' statement + with (new JavaImporter(java.io, + java.net, + java.lang.StringBuilder)) { + var buf = new StringBuilder(); + var u = new URL(url); + var reader = new BufferedReader( + new InputStreamReader(u.openStream())); + var line = null; + try { + while ((line = reader.readLine()) != null) + buf.append(line).append('\n'); + } finally { + reader.close(); + } + + return buf.toString(); + } +} + +print(readTextFromURL("https://twitter.com/")); diff --git a/samples/javalist.js b/samples/javalist.js new file mode 100644 index 00000000..8f3749b5 --- /dev/null +++ b/samples/javalist.js @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Java List elements accessed/modified via +// array element access/update syntax + +var ArrayList = Java.type("java.util.ArrayList"); +var list = new ArrayList(); + +// add elements to list by List's add method calls +list.add("js"); +list.add("ecmascript"); +list.add("nashorn"); + +// get by List's get(int) method +print(list[0]); +print(list[1]); +print(list[2]); + +// access list elements by indexed access as well +print(list[0]); +print(list[1]); +print(list[2]); + +// assign to list elements by index as well +list[0] = list[0].toUpperCase(); +list[1] = list[1].toUpperCase(); +list[2] = list[2].toUpperCase(); + +print(list.get(0)); +print(list.get(1)); +print(list.get(2)); +print(list[0]); +print(list[1]); +print(list[2]); diff --git a/samples/javamap.js b/samples/javamap.js new file mode 100644 index 00000000..a53d0320 --- /dev/null +++ b/samples/javamap.js @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Java Map keys as properties + +// Demonstrating Java Map key/value can be accessed +// as property/value from script. + +var HashMap = Java.type("java.util.HashMap"); +var map = new HashMap(); + +// map key-value access by java get/put method calls +map.put('js', 'nashorn'); +print(map.get('js')); + +// access keys of map as properties +print(map['js']); +print(map.js); + +// also assign new key-value pair +// as 'property-value' +map['language'] = 'java'; +print(map.get("language")); +print(map.language); +print(map['language']); + +map.answer = 42; +print(map.get("answer")); +print(map.answer); +print(map['answer']); diff --git a/samples/javashell.js b/samples/javashell.js new file mode 100644 index 00000000..65d1a8a2 --- /dev/null +++ b/samples/javashell.js @@ -0,0 +1,146 @@ +#// Usage: jjs -scripting javashell.js + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Simple Java "shell" with which you can try out +// your few liner Java code leaving imports, main etc. +// And you can leave even compilation as this script +// takes care boilerplate+compile step for you. + +// Java types used +var Arrays = Java.type("java.util.Arrays"); +var BufferedReader = Java.type("java.io.BufferedReader"); +var FileWriter = Java.type("java.io.FileWriter"); +var LocalDateTime = Java.type("java.time.LocalDateTime"); +var InputStreamReader = Java.type("java.io.InputStreamReader"); +var PrintWriter = Java.type("java.io.PrintWriter"); +var ProcessBuilder = Java.type("java.lang.ProcessBuilder"); +var System = Java.type("java.lang.System"); + +// read multiple lines of input from stdin till user +// enters an empty line +function input(endMarker, prompt) { + if (!endMarker) { + endMarker = ""; + } + + if (!prompt) { + prompt = " >> "; + } + + var str = ""; + var reader = new BufferedReader(new InputStreamReader(System.in)); + var line; + while (true) { + System.out.print(prompt); + line = reader.readLine(); + if (line == null || line == endMarker) { + break; + } + str += line + "\n"; + } + return str; +} + +// write the string to the given file +function writeTo(file, str) { + var w = new PrintWriter(new FileWriter(file)); + try { + w.print(str); + } finally { + w.close(); + } +} + +// generate Java code with user's input +// put inside generated main method +function generate(className) { + var usercode = input(); + if (usercode == "") { + return false; + } + + var fullcode = <<EOF +// userful imports, add more here if you want +// more imports. +import static java.lang.System.*; +import java.io.*; +import java.net.*; +import java.math.*; +import java.nio.file.*; +import java.time.*; +import java.time.chrono.*; +import java.time.format.*; +import java.time.temporal.*; +import java.time.zone.*; +import java.util.*; +import java.util.concurrent.*; +import java.util.function.*; +import java.util.stream.*; + +public class ${className} { + public static void main(String[] args) throws Exception { + ${usercode} + } +} +EOF + + writeTo("${className}.java", fullcode); + return true; +} + +// execute code command +function exec(args) { + // build child process and start it! + new ProcessBuilder(Arrays.asList(args.split(' '))) + .inheritIO() + .start() + .waitFor(); +} + +// generate unique name +function uniqueName() { + var now = LocalDateTime.now().toString(); + // replace unsafe chars with '_' + return "JavaShell" + now.replace(/-|:|\./g, '_'); +} + +// read-compile-run loop +while(true) { + var className = uniqueName(); + if (generate(className)) { + exec("javac ${className}.java"); + exec("java ${className}"); + } else { + break; + } +} diff --git a/samples/jsadapter_dom.js b/samples/jsadapter_dom.js new file mode 100644 index 00000000..e86c6d2f --- /dev/null +++ b/samples/jsadapter_dom.js @@ -0,0 +1,189 @@ +#// Usage: jjs -scripting jsadapter_dom.js + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Simple example that demonstrates reading XML Rss feed +// to generate a HTML file from script and show it by browser +// Uses XML DOM parser and DOM element wrapped by script +// "proxy" (JSAdapter constructor) + +// Java classes used +var DocBuilderFac = Java.type("javax.xml.parsers.DocumentBuilderFactory"); +var Node = Java.type("org.w3c.dom.Node"); +var File = Java.type("java.io.File"); +var FileWriter = Java.type("java.io.FileWriter"); +var PrintWriter = Java.type("java.io.PrintWriter"); + +// constants from Node class +var ELEMENT_NODE = Node.ELEMENT_NODE; +var TEXT_NODE = Node.TEXT_NODE; + +// parse XML from uri and return Document +function parseXML(uri) { + var docBuilder = DocBuilderFac.newInstance().newDocumentBuilder(); + return docBuilder["parse(java.lang.String)"](uri); +} + +// get child Elements of given name of the parent element given +function getChildElements(elem, name) { + var nodeList = elem.childNodes; + var childElems = []; + var len = nodeList.length; + for (var i = 0; i < len; i++) { + var node = nodeList.item(i); + if (node.nodeType == ELEMENT_NODE && + node.tagName == name) { + childElems.push(wrapElement(node)); + } + } + + return childElems; +} + +// get concatenated child text content of an Element +function getElemText(elem) { + var nodeList = elem.childNodes; + var len = nodeList.length; + var text = ''; + for (var i = 0; i < len; i++) { + var node = nodeList.item(i); + if (node.nodeType == TEXT_NODE) { + text += node.nodeValue; + } + } + + return text; +} + +// Wrap DOM Element object as a convenient script object +// using JSAdapter. JSAdapter is like java.lang.reflect.Proxy +// in that it allows property access, method calls be trapped +// by 'magic' methods like __get__, __call__. +function wrapElement(elem) { + if (! elem) { + return elem; + } + return new JSAdapter() { + // getter to expose child elements and attributes by name + __get__: function(name) { + if (typeof name == 'string') { + if (name.startsWith('@')) { + var attr = elem.getAttributeNode(name.substring(1)); + return !attr? undefined : attr.value; + } + + var arr = getChildElements(elem, name); + if (arr.length == 1) { + // single child element, expose as single element + return arr[0]; + } else { + // multiple children of given name, expose as array + return arr; + } + } + return undefined; + }, + + __call__: function(name) { + // toString override to get text content of this Element + if (name == 'toString' || name == 'valueOf') { + return getElemText(elem); + } + return undefined; + } + } +} + +// generate HTML using here-doc and string interpolation +function getBooksHtml() { + var doc = parseXML("http://www.gutenberg.org/cache/epub/feeds/today.rss"); + // wrap document root Element as script convenient object + var rss = wrapElement(doc.documentElement); + print("rss file version " + rss['@version']); + + var str = <<HEAD + +<html> +<title>${rss.channel.title}</title> +<body> +<h1>${rss.channel.description}</h1> +<p> +Published on ${rss.channel.pubDate} +</p> + +HEAD + + var items = rss.channel.item; + for each (var i in items) { + str += <<LIST + +<dl> +<dt><a href="${i.link}">${i.title}</a></dt> +<dd>${i.description}</dd> +</dl> + +LIST + } + str += <<END + +</body> +</html> + +END + return str; +} + +// write the string to the given file +function writeTo(file, str) { + var w = new PrintWriter(new FileWriter(file)); + try { + w.print(str); + } finally { + w.close(); + } +} + +// generate books HTML +var str = getBooksHtml(); + +// write to file. __DIR__ is directory where +// this script is stored. +var file = new File(__DIR__ + "books.html"); +writeTo(file, str); + +// show it by desktop browser +try { + var Desktop = Java.type("java.awt.Desktop"); + Desktop.desktop.browse(file.toURI()); +} catch (e) { + print(e); +} diff --git a/samples/jsobject.js b/samples/jsobject.js new file mode 100644 index 00000000..48434d7d --- /dev/null +++ b/samples/jsobject.js @@ -0,0 +1,75 @@ +#// Usage: jjs -scripting -cp . jsobject.js + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This sample demonstrats how to expose a +// script friendly object from your java code +// by implementing jdk.nashorn.api.scripting.JSObject + +// compile the java program +`javac BufferArray.java`; + +// print error, if any and exit +if ($ERR != '') { + print($ERR); + exit($EXIT); +} + +// create BufferArray +var BufferArray = Java.type("BufferArray"); +var bb = new BufferArray(10); + +// 'magic' methods called to retrieve set/get +// properties on BufferArray instance +var len = bb.length; +print("bb.length = " + len) +for (var i = 0; i < len; i++) { + bb[i] = i*i; +} + +for (var i = 0; i < len; i++) { + print(bb[i]); +} + +// get underlying buffer by calling a method +// on BufferArray magic object + +// 'buf' is a function member +print(typeof bb.buf); +var buf = bb.buf(); + +// use retrieved underlying nio buffer +var cap = buf.capacity(); +print("buf.capacity() = " + cap); +for (var i = 0; i < cap; i++) { + print(buf.get(i)); +} diff --git a/samples/jsobject_mapreduce.js b/samples/jsobject_mapreduce.js new file mode 100644 index 00000000..ff34940b --- /dev/null +++ b/samples/jsobject_mapreduce.js @@ -0,0 +1,62 @@ +#// Usage: jjs -scripting -cp . jsobject_mapreduce.js + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Many Array.prototype functions such as map, +// filter, reduce, reduceRight, every, some are generic. +// These functions accept ECMAScript array as well as +// many array-like objects including JSObjects. +// See also http://en.wikipedia.org/wiki/MapReduce + +`javac BufferArray.java`; + +var BufferArray = Java.type("BufferArray"); +var buf = new BufferArray(10); + +var map = Array.prototype.map; +var filter = Array.prototype.filter; +var reduce = Array.prototype.reduce; + +// make random list of numbers +for (var i = 0; i < 10; i++) + buf[i] = Math.random(); + +var forEach = Array.prototype.forEach; +// print numbers in the list +forEach.call(buf, function(x) print(x)); + +// print sum of squares of the random numbers +print("Square sum:", + reduce.call( + map.call(buf, function(x) x*x), + function(x, y) x + y) +); diff --git a/samples/jsonviewer.js b/samples/jsonviewer.js new file mode 100644 index 00000000..804fef50 --- /dev/null +++ b/samples/jsonviewer.js @@ -0,0 +1,120 @@ +#// Usage: jjs -fx jsonviewer.js +// or +// jjs -fx jsonviewer.js -- <url-of-json-doc> + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +if (! $OPTIONS._fx) { + print("Usage: jjs -fx jsonviewer.js -- <url-of-json-doc>"); + exit(1); +} + +// This example downloads a JSON file from a URL and +// shows the same as a JavaFX tree view. + +// Using JavaFX from Nashorn. See also: +// http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/javafx.html + +// JavaFX classes used +var StackPane = Java.type("javafx.scene.layout.StackPane"); +var Scene = Java.type("javafx.scene.Scene"); +var TreeItem = Java.type("javafx.scene.control.TreeItem"); +var TreeView = Java.type("javafx.scene.control.TreeView"); + +// read text content of a URL +function readTextFromURL(url) { + // equivalent to + // + // import java.io.*; + // import java.net.*; + // import java.lang.StringBuffer; + // + // only inside the 'with' statement + with (new JavaImporter(java.io, + java.net, + java.lang.StringBuilder)) { + var buf = new StringBuilder(); + var u = new URL(url); + var reader = new BufferedReader( + new InputStreamReader(u.openStream())); + var line = null; + try { + while ((line = reader.readLine()) != null) + buf.append(line).append('\n'); + } finally { + reader.close(); + } + + return buf.toString(); + } +} + +// Create a javafx TreeItem to view a script object +function treeItemForObject(obj, name) { + var item = new TreeItem(name); + for (var prop in obj) { + var node = obj[prop]; + if (typeof node == 'object') { + if (node == null) { + // skip nulls + continue; + } + + if (Array.isArray(node) && node.length == 0) { + // skip empty arrays + continue; + } + + var subitem = treeItemForObject(node, prop); + } else { + var subitem = new TreeItem(prop + ": " + node); + } + item.children.add(subitem); + } + return item; +} + +var DEFAULT_URL = "http://api.openweathermap.org/data/2.5/forecast/daily?q=Chennai&mode=json&units=metric&cnt=7`"; + +var url = arguments.length == 0? DEFAULT_URL : arguments[0]; +var obj = JSON.parse(readTextFromURL(url)); + +// JavaFX start method +function start(stage) { + stage.title = "JSON Viewer"; + var rootItem = treeItemForObject(obj, url); + var tree = new TreeView(rootItem); + var root = new StackPane(); + root.children.add(tree); + stage.scene = new Scene(root, 300, 450); + stage.show(); +} diff --git a/samples/letter.js b/samples/letter.js index cbee92d0..304bf1fb 100644 --- a/samples/letter.js +++ b/samples/letter.js @@ -1,3 +1,5 @@ +#// Usage: jjs -scripting letter.js -- <sender> <recipient> + /* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. * diff --git a/samples/list_mapreduce.js b/samples/list_mapreduce.js new file mode 100644 index 00000000..033f4d76 --- /dev/null +++ b/samples/list_mapreduce.js @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Usage: jjs list_mapreduce.js + +// Many Array.prototype functions such as map, +// filter, reduce, reduceRight, every, some are generic. +// These functions accept ECMAScript array as well as +// many array-like objects including java.util.ArrayLists. +// So, you can do map/filter/reduce with Java streams or +// you can also use Array.prototype functions as below. +// See also http://en.wikipedia.org/wiki/MapReduce + +var ArrayList = Java.type("java.util.ArrayList"); +var list = new ArrayList(); +list.add("nashorn"); +list.add("ecmascript"); +list.add("javascript"); +list.add("js"); +list.add("scheme"); + +var map = Array.prototype.map; +var filter = Array.prototype.filter; +var reduce = Array.prototype.reduce; + +// sum of word lengths +print("Sum word length:", + reduce.call( + map.call(list, function(x) x.length), + function(x, y) x + y) +); + +// filter use to filter out "j*" and concatenate rest with ":" +// after uppercasing all strings +print( + reduce.call( + map.call( + filter.call(list, function(x) !x.startsWith("j")), + function(x) x.toUpperCase()), + function(x, y) x + ":" + y) +); + +// another list example involving numbers +list.clear(); +// make random list of numbers +for (var i = 0; i < 10; i++) + list.add(Math.random()); + +var forEach = Array.prototype.forEach; +// print numbers in the list +forEach.call(list, function(x) print(x)); + +// print sum of squares of the random numbers +print("Square sum:", + reduce.call( + map.call(list, function(x) x*x), + function(x, y) x + y) +); diff --git a/samples/locales.js b/samples/locales.js new file mode 100644 index 00000000..ae42f969 --- /dev/null +++ b/samples/locales.js @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Simple program that lists available locals. This is ECMAScript +// port of Java example by @brunoborges + +// Java classes used +var Arrays = Java.type("java.util.Arrays"); +var Collectors = Java.type("java.util.stream.Collectors"); +var JString = Java.type("java.lang.String"); +var Locale = Java.type("java.util.Locale"); + +var formatStr = "Country : %s \t\t\t\t:\t Country Code : %s"; + +// Nashorn allows script functions to be passed +// whereever Java8 lambdas are expected. + +// Nashorn also supports "expression closures" supported by +// Mozilla JavaScript 1.8 version. See also +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/1.8 + +// The following prints locales in (country) display name order +var list = Arrays.asList(Locale.getISOCountries()) + .stream() + .map(function(x) new Locale("", x)) + .sorted(function(c0, c1) c0.displayCountry.compareTo(c1.displayCountry)) + .map(function(l) JString.format(formatStr, l.displayCountry, l.country)) + .collect(Collectors.toList()); + +list.forEach(print); diff --git a/samples/logisticmap.js b/samples/logisticmap.js new file mode 100644 index 00000000..74198475 --- /dev/null +++ b/samples/logisticmap.js @@ -0,0 +1,82 @@ +#// Usage: jjs -fx -scripting logisticmap.js -- <initial_x> <R> + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Logistic map viewer using Java8 Streams and JavaFX +// See also http://en.wikipedia.org/wiki/Logistic_map + +if (!$OPTIONS._fx || arguments.length < 2) { + print("Usage: jjs -fx -scripting logisticmap.js -- <initial_x> <R>"); + exit(1); +} + +// parameters for the logistic map +var x = parseFloat(arguments[0]); +var R = parseFloat(arguments[1]); +var NUM_POINTS = arguments.length > 2? parseFloat(arguments[2]) : 20; + +// Java classes used +var DoubleStream = Java.type('java.util.stream.DoubleStream'); +var LineChart = Java.type("javafx.scene.chart.LineChart"); +var NumberAxis = Java.type("javafx.scene.chart.NumberAxis"); +var Scene = Java.type("javafx.scene.Scene"); +var Stage = Java.type("javafx.stage.Stage"); +var XYChart = Java.type("javafx.scene.chart.XYChart"); + +function start(stage) { + stage.title = "Logistic Map: initial x = ${x}, R = ${R}"; + // make chart + var xAxis = new NumberAxis(); + var yAxis = new NumberAxis(); + var lineChart = new LineChart(xAxis, yAxis); + xAxis.setLabel("iteration"); + yAxis.setLabel("x"); + // make chart data series + var series = new XYChart.Series(); + var data = series.data; + // populate data using logistic iteration + var i = 0; + DoubleStream + .generate(function() x = R*x*(1-x)) + .limit(NUM_POINTS) + .forEach( + function(value) { + data.add(new XYChart.Data(i, value)); + i++; + } + ); + // add to stage + var scene = new Scene(lineChart, 800, 600); + lineChart.data.add(series); + stage.scene = scene; + stage.show(); +} diff --git a/samples/options.js b/samples/options.js new file mode 100644 index 00000000..3a10346c --- /dev/null +++ b/samples/options.js @@ -0,0 +1,37 @@ +#// Usage: jjs -scripting options.js + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// print all option names and values +for (i in $OPTIONS) { + print(i, '=', $OPTIONS[i]); +} diff --git a/samples/readLine.js b/samples/readLine.js new file mode 100644 index 00000000..9807d3b5 --- /dev/null +++ b/samples/readLine.js @@ -0,0 +1,38 @@ +#// Usage: jjs -scripting greeting.js + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// readLine prints prompt and reads user response +var name = readLine("Your name please: "); + +// user name is interpolated within string +print("Hello ${name}"); diff --git a/samples/sam_function.js b/samples/sam_function.js new file mode 100644 index 00000000..84064732 --- /dev/null +++ b/samples/sam_function.js @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// nashorn supports passing script functions whenever +// a SAM (single abstract method) type object is expected + +var System = Java.type("java.lang.System"); +var Timer = Java.type("java.util.Timer"); +var timer = new Timer(); + +// schedule method accepts java.util.TimerTask +// which is a single-abstract-method type. you +// can pass a script function and nashorn will +// wrap it as SAM implementor. + +timer.schedule(function() { + print("Hello World!"); +}, 1000); + +// wait for timer thread to print by +// reading from stdin. +print("press any key to exit after message from timer..."); +System.in.read(); diff --git a/samples/shell.js b/samples/shell.js index fc4ce9aa..93965387 100644 --- a/samples/shell.js +++ b/samples/shell.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,50 +29,53 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * This is a simple shell tool in JavaScript. +// Usage: jjs shell.js + +/* This is a simple shell tool in JavaScript. * * Runs any operating system command using Java "exec". When "eval" command is * used, evaluates argument(s) as JavaScript code. */ -var imports = new JavaImporter(java.io, java.lang, java.util); +(function() { + // Java classes used + var Arrays = Java.type("java.util.Arrays"); + var BufferedReader = Java.type("java.io.BufferedReader"); + var InputStreamReader = Java.type("java.io.InputStreamReader"); + var ProcessBuilder = Java.type("java.lang.ProcessBuilder"); + var System = Java.type("java.lang.System"); -function prompt() { - java.lang.System.out.print(">"); -} + // print prompt + function prompt() { + System.out.print("> "); + } -with (imports) { - var reader = new BufferedReader(new InputStreamReader(System["in"])); - var line = null; + var reader = new BufferedReader(new InputStreamReader(System.in)); prompt(); - while ((line = reader.readLine()) != null) { - if (line != "") { - var args = line.split(" "); + // read and evaluate each line from stdin + reader.lines().forEach(function(line) { + if (! line.isEmpty()) { + var args = line.split(' '); try { - if (args[0] == "eval") { - var code = line.substring("eval".length); + // special 'eval' command to evaluate JS code + if (args[0] == 'eval') { + var code = line.substring('eval'.length); var res = eval(code); if (res != undefined) { print(res); } } else { - var argList = new ArrayList(); - for (i in args) { argList.add(args[i]); } - var procBuilder = new ProcessBuilder(argList); - procBuilder.redirectErrorStream(); - var proc = procBuilder.start(); - var out = new BufferedReader(new InputStreamReader(proc.getInputStream())); - var line = null; - while ((line = out.readLine()) != null) { - System.out.println(line); - } - proc.waitFor(); + // build child process and start it! + new ProcessBuilder(Arrays.asList(args)) + .inheritIO() + .start() + .waitFor(); } } catch (e) { + // print exception, if any print(e); } } prompt(); - } -} + }) +})() diff --git a/samples/stack.js b/samples/stack.js new file mode 100644 index 00000000..295ad20f --- /dev/null +++ b/samples/stack.js @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// nashorn supports 'stack' property on ECMAScript +// error objects. This property's value is a string +// that shows script stack trace. + +function g() { + throw new Error("wrong"); +} + +function f() { + g(); +} + +// Output looks something like: +// +// Error: wrong +// at g (stack.js:37) +// at f (stack.js:41) +// at <program> (stack.js:52) + +try { + f(); +} catch (e) { + print(e.stack); +} diff --git a/samples/test.js b/samples/test.js index ecdaf846..1a7e8061 100644 --- a/samples/test.js +++ b/samples/test.js @@ -30,4 +30,3 @@ */ print("Hello World"); - diff --git a/samples/uniform_random.js b/samples/uniform_random.js new file mode 100644 index 00000000..a82cd0bb --- /dev/null +++ b/samples/uniform_random.js @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// generate/print 100 uniformly distributed random values +// and print summary statistics on it + +var DoubleStream = Java.type("java.util.stream.DoubleStream"); + +// pass script function when a lambda is required +// Math.random passed here for double generator lambda +// print passed to forEach method + +DoubleStream + .generate(Math.random) + .limit(100) + .forEach(print); + +print(DoubleStream + .generate(Math.random) + .limit(100) + .summaryStatistics()); diff --git a/samples/uniq.js b/samples/uniq.js index 3da8480b..cbd2c34d 100644 --- a/samples/uniq.js +++ b/samples/uniq.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,27 +29,28 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * Prints unique lines from a given file. - */ +// Usage: jjs uniq.js +// or: jjs uniq.js -- <file> -if (arguments.length != 1) { - print("Usage: jjs uniq.js -- <file>"); - java.lang.System.exit(1); -} +// omit repeated lines and print unique lines -var imports = new JavaImporter(java.io); +var BufferedReader = Java.type("java.io.BufferedReader"); +var FileReader = Java.type("java.io.FileReader"); +var InputStreamReader = Java.type("java.io.InputStreamReader"); +var System = Java.type("java.lang.System"); +// use object as set - but insertion order preserved var uniqueLines = {}; -with (imports) { - var reader = new BufferedReader(new FileReader(arguments[0])); - while ((line = reader.readLine()) != null) { - // using a JS object as a map... - uniqueLines[line] = true; - } -} +var reader = arguments.length > 0 ? + new FileReader(arguments[0]) : + new InputStreamReader(System.in); +reader = new BufferedReader(reader); + +// add unique lines +reader.lines().forEach(function(line) { + uniqueLines[line] = true; +}) -// now print the collected lines -for (i in uniqueLines) { - print(i); +for (line in uniqueLines) { + print(line); } diff --git a/samples/uniqs.js b/samples/uniqs.js new file mode 100644 index 00000000..57eb7c52 --- /dev/null +++ b/samples/uniqs.js @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Usage: jjs uniqs.js -- <file> +// omit repeated lines and print unique lines +// But this version uses Stream API + +if (arguments.length < 1) { + print("Usage: jjs uniqs.js -- <file>"); + exit(1); +} + +var Files = Java.type("java.nio.file.Files"); +var FileSystems = Java.type("java.nio.file.FileSystems"); +print('Unique lines:', + Files + .lines(FileSystems.default.getPath(arguments[0])) + .distinct() + .peek(print) + .count()); diff --git a/samples/weather.js b/samples/weather.js new file mode 100644 index 00000000..75c6b265 --- /dev/null +++ b/samples/weather.js @@ -0,0 +1,63 @@ +#// usage: jjs -scripting weather.js + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Simple nashorn example showing back-quote exec process, +// JSON and Java8 streams + +var Arrays = Java.type("java.util.Arrays"); + +// use curl to download JSON weather data from the net +// use backquote -scripting mode syntax to exec a process + +`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()); diff --git a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java index 9c14359e..7ebe5c91 100644 --- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java @@ -27,16 +27,14 @@ package jdk.nashorn.api.scripting; import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; +import static jdk.nashorn.internal.runtime.Source.sourceFor; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.io.Reader; import java.lang.invoke.MethodHandles; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URL; -import java.nio.charset.Charset; import java.security.AccessControlContext; import java.security.AccessController; import java.security.Permissions; @@ -124,21 +122,21 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C } } - // load engine.js and return content as a char[] + // load engine.js @SuppressWarnings("resource") - private static char[] loadEngineJSSource() { + private static Source loadEngineJSSource() { final String script = "resources/engine.js"; try { - final InputStream is = AccessController.doPrivileged( - new PrivilegedExceptionAction<InputStream>() { + return AccessController.doPrivileged( + new PrivilegedExceptionAction<Source>() { @Override - public InputStream run() throws Exception { + public Source run() throws IOException { final URL url = NashornScriptEngine.class.getResource(script); - return url.openStream(); + return sourceFor(NashornException.ENGINE_SCRIPT_SOURCE_NAME, url); } - }); - return Source.readFully(new InputStreamReader(is)); - } catch (final PrivilegedActionException | IOException e) { + } + ); + } catch (final PrivilegedActionException e) { if (Context.DEBUG) { e.printStackTrace(); } @@ -147,7 +145,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C } // Source object for engine.js - private static final Source ENGINE_SCRIPT_SRC = new Source(NashornException.ENGINE_SCRIPT_SOURCE_NAME, loadEngineJSSource()); + private static final Source ENGINE_SCRIPT_SRC = loadEngineJSSource(); NashornScriptEngine(final NashornScriptEngineFactory factory, final ClassLoader appLoader) { this(factory, DEFAULT_OPTIONS, appLoader); @@ -282,19 +280,14 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C private static Source makeSource(final Reader reader, final ScriptContext ctxt) throws ScriptException { try { - if (reader instanceof URLReader) { - final URL url = ((URLReader)reader).getURL(); - final Charset cs = ((URLReader)reader).getCharset(); - return new Source(url.toString(), url, cs); - } - return new Source(getScriptName(ctxt), Source.readFully(reader)); - } catch (final IOException e) { + return sourceFor(getScriptName(ctxt), reader); + } catch (IOException e) { throw new ScriptException(e); } } private static Source makeSource(final String src, final ScriptContext ctxt) { - return new Source(getScriptName(ctxt), src); + return sourceFor(getScriptName(ctxt), src); } private static String getScriptName(final ScriptContext ctxt) { @@ -532,6 +525,31 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt)); } + private Object evalImpl(final Context.MultiGlobalCompiledScript mgcs, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException { + final Global oldGlobal = Context.getGlobal(); + final boolean globalChanged = (oldGlobal != ctxtGlobal); + try { + if (globalChanged) { + Context.setGlobal(ctxtGlobal); + } + + final ScriptFunction script = mgcs.getFunction(ctxtGlobal); + + // set ScriptContext variables if ctxt is non-null + if (ctxt != null) { + setContextVariables(ctxtGlobal, ctxt); + } + return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal)); + } catch (final Exception e) { + throwAsScriptException(e, ctxtGlobal); + throw new AssertionError("should not reach here"); + } finally { + if (globalChanged) { + Context.setGlobal(oldGlobal); + } + } + } + private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException { if (script == null) { return null; @@ -578,18 +596,38 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C } private CompiledScript asCompiledScript(final Source source) throws ScriptException { - final ScriptFunction func = compileImpl(source, context); + final Context.MultiGlobalCompiledScript mgcs; + final ScriptFunction func; + final Global oldGlobal = Context.getGlobal(); + final Global newGlobal = getNashornGlobalFrom(context); + final boolean globalChanged = (oldGlobal != newGlobal); + try { + if (globalChanged) { + Context.setGlobal(newGlobal); + } + + mgcs = nashornContext.compileScript(source); + func = mgcs.getFunction(newGlobal); + } catch (final Exception e) { + throwAsScriptException(e, newGlobal); + throw new AssertionError("should not reach here"); + } finally { + if (globalChanged) { + Context.setGlobal(oldGlobal); + } + } + return new CompiledScript() { @Override public Object eval(final ScriptContext ctxt) throws ScriptException { final Global globalObject = getNashornGlobalFrom(ctxt); - // Are we running the script in the correct global? + // Are we running the script in the same global in which it was compiled? if (func.getScope() == globalObject) { return evalImpl(func, ctxt, globalObject); } - // ScriptContext with a different global. Compile again! - // Note that we may still hit per-global compilation cache. - return evalImpl(compileImpl(source, ctxt), ctxt, globalObject); + + // different global + return evalImpl(mgcs, ctxt, globalObject); } @Override public ScriptEngine getEngine() { diff --git a/src/jdk/nashorn/internal/codegen/CodeGenerator.java b/src/jdk/nashorn/internal/codegen/CodeGenerator.java index 9cf0adb9..882846c6 100644 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java @@ -1451,7 +1451,10 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex if (value == null) { hasGettersSetters = true; - } else if (key.equals(ScriptObject.PROTO_PROPERTY_NAME)) { + } else if (propertyNode.getKey() instanceof IdentNode && + key.equals(ScriptObject.PROTO_PROPERTY_NAME)) { + // ES6 draft compliant __proto__ inside object literal + // Identifier key and name is __proto__ protoNode = value; continue; } diff --git a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java index 4702057a..ef7f8a1b 100644 --- a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java +++ b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java @@ -25,6 +25,8 @@ package jdk.nashorn.internal.ir.debug; +import static jdk.nashorn.internal.runtime.Source.sourceFor; + import java.util.Arrays; import java.util.List; import java.util.ArrayList; @@ -88,7 +90,7 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> { * @return JSON string representation of AST of the supplied code */ public static String parse(final ScriptEnvironment env, final String code, final String name, final boolean includeLoc) { - final Parser parser = new Parser(env, new Source(name, code), new Context.ThrowErrorManager(), env._strict); + final Parser parser = new Parser(env, sourceFor(name, code), new Context.ThrowErrorManager(), env._strict); final JSONWriter jsonWriter = new JSONWriter(includeLoc); try { final FunctionNode functionNode = parser.parse(CompilerConstants.RUN_SCRIPT.symbolName()); diff --git a/src/jdk/nashorn/internal/objects/Global.java b/src/jdk/nashorn/internal/objects/Global.java index 9e40dbeb..00019382 100644 --- a/src/jdk/nashorn/internal/objects/Global.java +++ b/src/jdk/nashorn/internal/objects/Global.java @@ -1906,6 +1906,13 @@ public final class Global extends ScriptObject implements Scope { // Object.getPrototypeOf(Function.prototype) === Object.prototype anon.setInitialProto(ObjectPrototype); + // ES6 draft compliant __proto__ property of Object.prototype + // accessors on Object.prototype for "__proto__" + final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", ScriptObject.GETPROTO); + final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", ScriptObject.SETPROTOCHECK); + ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto); + + // Function valued properties of Function.prototype were not properly // initialized. Because, these were created before global.function and // global.object were not initialized. diff --git a/src/jdk/nashorn/internal/objects/NativeFunction.java b/src/jdk/nashorn/internal/objects/NativeFunction.java index 3d45cc1f..013683e0 100644 --- a/src/jdk/nashorn/internal/objects/NativeFunction.java +++ b/src/jdk/nashorn/internal/objects/NativeFunction.java @@ -27,6 +27,7 @@ package jdk.nashorn.internal.objects; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; +import static jdk.nashorn.internal.runtime.Source.sourceFor; import java.util.List; @@ -257,7 +258,7 @@ public final class NativeFunction { } private static void checkFunctionParameters(final String params) { - final Source src = new Source("<function>", params); + final Source src = sourceFor("<function>", params); final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager()); try { parser.parseFormalParameterList(); @@ -267,7 +268,7 @@ public final class NativeFunction { } private static void checkFunctionBody(final String funcBody) { - final Source src = new Source("<function>", funcBody); + final Source src = sourceFor("<function>", funcBody); final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager()); try { parser.parseFunctionBody(); diff --git a/src/jdk/nashorn/internal/parser/Parser.java b/src/jdk/nashorn/internal/parser/Parser.java index 08ff725a..6ad60b58 100644 --- a/src/jdk/nashorn/internal/parser/Parser.java +++ b/src/jdk/nashorn/internal/parser/Parser.java @@ -33,6 +33,7 @@ import static jdk.nashorn.internal.parser.TokenType.CASE; import static jdk.nashorn.internal.parser.TokenType.CATCH; import static jdk.nashorn.internal.parser.TokenType.COLON; import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT; +import static jdk.nashorn.internal.parser.TokenType.CONST; import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX; import static jdk.nashorn.internal.parser.TokenType.DECPREFIX; import static jdk.nashorn.internal.parser.TokenType.ELSE; @@ -849,6 +850,11 @@ loop: expect(SEMICOLON); break; default: + if (env._const_as_var && type == CONST) { + variableStatement(true); + break; + } + if (type == IDENT || isNonStrictModeIdent()) { if (T(k + 1) == COLON) { labelStatement(); @@ -1110,6 +1116,12 @@ loop: case SEMICOLON: break; default: + if (env._const_as_var && type == CONST) { + // Var statements captured in for outer block. + vars = variableStatement(false); + break; + } + final Expression expression = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true); forNode = forNode.setInit(lc, expression); break; diff --git a/src/jdk/nashorn/internal/parser/TokenType.java b/src/jdk/nashorn/internal/parser/TokenType.java index 5c696cb9..59005077 100644 --- a/src/jdk/nashorn/internal/parser/TokenType.java +++ b/src/jdk/nashorn/internal/parser/TokenType.java @@ -111,7 +111,7 @@ public enum TokenType { CATCH (KEYWORD, "catch"), // CHAR (FUTURE, "char"), CLASS (FUTURE, "class"), - CONST (FUTURE, "const"), + CONST (KEYWORD, "const"), CONTINUE (KEYWORD, "continue"), DEBUGGER (KEYWORD, "debugger"), DEFAULT (KEYWORD, "default"), diff --git a/src/jdk/nashorn/internal/runtime/Context.java b/src/jdk/nashorn/internal/runtime/Context.java index c4fa6e0d..9f2c521d 100644 --- a/src/jdk/nashorn/internal/runtime/Context.java +++ b/src/jdk/nashorn/internal/runtime/Context.java @@ -32,6 +32,7 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE; import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; +import static jdk.nashorn.internal.runtime.Source.sourceFor; import java.io.File; import java.io.IOException; @@ -490,6 +491,39 @@ public final class Context { } /** + * Interface to represent compiled code that can be re-used across many + * global scope instances + */ + public static interface MultiGlobalCompiledScript { + /** + * Obtain script function object for a specific global scope object. + * + * @param newGlobal global scope for which function object is obtained + * @return script function for script level expressions + */ + public ScriptFunction getFunction(final Global newGlobal); + } + + /** + * Compile a top level script. + * + * @param source the script source + * @return reusable compiled script across many global scopes. + */ + public MultiGlobalCompiledScript compileScript(final Source source) { + final Class<?> clazz = compile(source, this.errors, this._strict); + final MethodHandle runMethodHandle = getRunScriptHandle(clazz); + final boolean strict = isStrict(clazz); + + return new MultiGlobalCompiledScript() { + @Override + public ScriptFunction getFunction(final Global newGlobal) { + return Context.getGlobal().newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, newGlobal, strict); + } + }; + } + + /** * Entry point for {@code eval} * * @param initialScope The scope of this eval call @@ -502,7 +536,7 @@ public final class Context { */ public Object eval(final ScriptObject initialScope, final String string, final Object callThis, final Object location, final boolean strict) { final String file = (location == UNDEFINED || location == null) ? "<eval>" : location.toString(); - final Source source = new Source(file, string); + final Source source = sourceFor(file, string); final boolean directEval = location != UNDEFINED; // is this direct 'eval' call or indirectly invoked eval? final Global global = Context.getGlobal(); @@ -569,7 +603,7 @@ public final class Context { public Source run() { try { final URL resURL = Context.class.getResource(resource); - return (resURL != null)? new Source(srcStr, resURL) : null; + return (resURL != null)? sourceFor(srcStr, resURL) : null; } catch (final IOException exp) { return null; } @@ -601,7 +635,7 @@ public final class Context { final String srcStr = (String)src; if (srcStr.startsWith(LOAD_CLASSPATH)) { URL url = getResourceURL(srcStr.substring(LOAD_CLASSPATH.length())); - source = (url != null)? new Source(url.toString(), url) : null; + source = (url != null)? sourceFor(url.toString(), url) : null; } else { final File file = new File(srcStr); if (srcStr.indexOf(':') != -1) { @@ -614,31 +648,31 @@ public final class Context { } catch (final MalformedURLException e) { url = file.toURI().toURL(); } - source = new Source(url.toString(), url); + source = sourceFor(url.toString(), url); } } else if (file.isFile()) { - source = new Source(srcStr, file); + source = sourceFor(srcStr, file); } } } else if (src instanceof File && ((File)src).isFile()) { final File file = (File)src; - source = new Source(file.getName(), file); + source = sourceFor(file.getName(), file); } else if (src instanceof URL) { final URL url = (URL)src; - source = new Source(url.toString(), url); + source = sourceFor(url.toString(), url); } else if (src instanceof ScriptObject) { final ScriptObject sobj = (ScriptObject)src; if (sobj.has("script") && sobj.has("name")) { final String script = JSType.toString(sobj.get("script")); final String name = JSType.toString(sobj.get("name")); - source = new Source(name, script); + source = sourceFor(name, script); } } else if (src instanceof Map) { final Map<?,?> map = (Map<?,?>)src; if (map.containsKey("script") && map.containsKey("name")) { final String script = JSType.toString(map.get("script")); final String name = JSType.toString(map.get("name")); - source = new Source(name, script); + source = sourceFor(name, script); } } @@ -949,14 +983,8 @@ public final class Context { return ScriptRuntime.apply(script, thiz); } - private static ScriptFunction getRunScriptFunction(final Class<?> script, final ScriptObject scope) { - if (script == null) { - return null; - } - - // Get run method - the entry point to the script - final MethodHandle runMethodHandle = - MH.findStatic( + private static MethodHandle getRunScriptHandle(final Class<?> script) { + return MH.findStatic( MethodHandles.lookup(), script, RUN_SCRIPT.symbolName(), @@ -964,14 +992,24 @@ public final class Context { Object.class, ScriptFunction.class, Object.class)); + } - boolean strict; - + private static boolean isStrict(final Class<?> script) { try { - strict = script.getField(STRICT_MODE.symbolName()).getBoolean(null); + return script.getField(STRICT_MODE.symbolName()).getBoolean(null); } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { - strict = false; + return false; } + } + + private static ScriptFunction getRunScriptFunction(final Class<?> script, final ScriptObject scope) { + if (script == null) { + return null; + } + + // Get run method - the entry point to the script + final MethodHandle runMethodHandle = getRunScriptHandle(script); + boolean strict = isStrict(script); // Package as a JavaScript function and pass function back to shell. return Context.getGlobal().newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, scope, strict); diff --git a/src/jdk/nashorn/internal/runtime/JSONFunctions.java b/src/jdk/nashorn/internal/runtime/JSONFunctions.java index f12945fe..ab1de42f 100644 --- a/src/jdk/nashorn/internal/runtime/JSONFunctions.java +++ b/src/jdk/nashorn/internal/runtime/JSONFunctions.java @@ -39,6 +39,8 @@ import jdk.nashorn.internal.parser.TokenType; import jdk.nashorn.internal.runtime.arrays.ArrayIndex; import jdk.nashorn.internal.runtime.linker.Bootstrap; +import static jdk.nashorn.internal.runtime.Source.sourceFor; + /** * Utilities used by "JSON" object implementation. */ @@ -77,9 +79,7 @@ public final class JSONFunctions { */ public static Object parse(final Object text, final Object reviver) { final String str = JSType.toString(text); - final JSONParser parser = new JSONParser( - new Source("<json>", str), - new Context.ThrowErrorManager()); + final JSONParser parser = new JSONParser(sourceFor("<json>", str), new Context.ThrowErrorManager()); Node node; diff --git a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java index 96982011..445106d7 100644 --- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java +++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java @@ -62,6 +62,9 @@ public final class ScriptEnvironment { /** Only compile script, do not run it or generate other ScriptObjects */ public final boolean _compile_only; + /** Accept "const" keyword and treat it as variable. Interim feature */ + public final boolean _const_as_var; + /** Accumulated callsite flags that will be used when bootstrapping script callsites */ public final int _callsite_flags; @@ -200,6 +203,7 @@ public final class ScriptEnvironment { _class_cache_size = options.getInteger("class.cache.size"); _compile_only = options.getBoolean("compile.only"); + _const_as_var = options.getBoolean("const.as.var"); _debug_lines = options.getBoolean("debug.lines"); _dest_dir = options.getString("d"); _dump_on_error = options.getBoolean("doe"); diff --git a/src/jdk/nashorn/internal/runtime/ScriptObject.java b/src/jdk/nashorn/internal/runtime/ScriptObject.java index 1519024a..d4556d89 100644 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java @@ -91,7 +91,7 @@ import jdk.nashorn.internal.runtime.linker.NashornGuards; */ public abstract class ScriptObject implements PropertyAccess { - /** __proto__ special property name */ + /** __proto__ special property name inside object literals. ES6 draft. */ public static final String PROTO_PROPERTY_NAME = "__proto__"; /** Search fall back routine name for "no such method" */ @@ -130,8 +130,10 @@ public abstract class ScriptObject implements PropertyAccess { /** Indexed array data. */ private ArrayData arrayData; - static final MethodHandle GETPROTO = findOwnMH("getProto", ScriptObject.class); - static final MethodHandle SETPROTOCHECK = findOwnMH("setProtoCheck", void.class, Object.class); + /** Method handle to retrive prototype of this object */ + public static final MethodHandle GETPROTO = findOwnMH("getProto", ScriptObject.class); + /** Method handle to set prototype of this object */ + public static final MethodHandle SETPROTOCHECK = findOwnMH("setProtoCheck", void.class, Object.class); static final MethodHandle MEGAMORPHIC_GET = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class, boolean.class); static final MethodHandle GLOBALFILTER = findOwnMH("globalFilter", Object.class, Object.class); @@ -1732,10 +1734,6 @@ public abstract class ScriptObject implements PropertyAccess { MethodHandle methodHandle; if (find == null) { - if (PROTO_PROPERTY_NAME.equals(name)) { - return new GuardedInvocation(GETPROTO, NashornGuards.getScriptObjectGuard()); - } - if ("getProp".equals(operator)) { return noSuchProperty(desc, request); } else if ("getMethod".equals(operator)) { @@ -1890,9 +1888,7 @@ public abstract class ScriptObject implements PropertyAccess { return createEmptySetMethod(desc, "property.not.writable", true); } } else { - if (PROTO_PROPERTY_NAME.equals(name)) { - return new GuardedInvocation(SETPROTOCHECK, NashornGuards.getScriptObjectGuard()); - } else if (! isExtensible()) { + if (! isExtensible()) { return createEmptySetMethod(desc, "object.non.extensible", false); } } diff --git a/src/jdk/nashorn/internal/runtime/Source.java b/src/jdk/nashorn/internal/runtime/Source.java index f57874bc..f7e890ff 100644 --- a/src/jdk/nashorn/internal/runtime/Source.java +++ b/src/jdk/nashorn/internal/runtime/Source.java @@ -27,13 +27,16 @@ package jdk.nashorn.internal.runtime; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOError; import java.io.IOException; import java.io.InputStream; import java.io.Reader; +import java.lang.ref.WeakReference; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; +import java.net.URLConnection; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -43,13 +46,19 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Objects; +import java.util.WeakHashMap; +import jdk.nashorn.api.scripting.URLReader; import jdk.nashorn.internal.parser.Token; /** * Source objects track the origin of JavaScript entities. - * */ public final class Source { + + private static final DebugLogger DEBUG = new DebugLogger("source"); + private static final int BUF_SIZE = 8 * 1024; + private static final Cache CACHE = new Cache(); + /** * Descriptive name of the source as supplied by the user. Used for error * reporting to the user. For example, SyntaxError will use this to print message. @@ -64,11 +73,8 @@ public final class Source { */ private final String base; - /** Cached source content. */ - private final char[] content; - - /** Length of source content. */ - private final int length; + /** Source content */ + private final Data data; /** Cached hash code */ private int hash; @@ -76,40 +82,297 @@ public final class Source { /** Message digest */ private byte[] digest; - /** Source URL if available */ - private final URL url; + // Do *not* make this public, ever! Trusts the URL and content. + private Source(final String name, final String base, final Data data) { + this.name = name; + this.base = base; + this.data = data; + } + + private static synchronized Source sourceFor(final String name, final String base, final URLData data) throws IOException { + try { + final Source newSource = new Source(name, base, data); + final Source existingSource = CACHE.get(newSource); + if (existingSource != null) { + // Force any access errors + data.checkPermissionAndClose(); + return existingSource; + } else { + // All sources in cache must be fully loaded + data.load(); + CACHE.put(newSource, newSource); + return newSource; + } + } catch (RuntimeException e) { + final Throwable cause = e.getCause(); + if (cause instanceof IOException) { + throw (IOException) cause; + } + throw e; + } + } + + private static class Cache extends WeakHashMap<Source, WeakReference<Source>> { + public Source get(final Source key) { + final WeakReference<Source> ref = super.get(key); + return ref == null ? null : ref.get(); + } + + public void put(final Source key, final Source value) { + assert !(value.data instanceof RawData); + put(key, new WeakReference<>(value)); + } + } + + // Wrapper to manage lazy loading + private static interface Data { + + URL url(); + + int length(); + + long lastModified(); + + char[] array(); + } + + private static class RawData implements Data { + private final char[] array; + private int hash; + + private RawData(final char[] array) { + this.array = Objects.requireNonNull(array); + } + + private RawData(final String source) { + this.array = Objects.requireNonNull(source).toCharArray(); + } + + private RawData(final Reader reader) throws IOException { + this(readFully(reader)); + } + + @Override + public int hashCode() { + int h = hash; + if (h == 0) { + h = hash = Arrays.hashCode(array); + } + return h; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof RawData) { + return Arrays.equals(array, ((RawData)obj).array); + } + return false; + } + + @Override + public String toString() { + return new String(array()); + } + + @Override + public URL url() { + return null; + } + + @Override + public int length() { + return array.length; + } + + @Override + public long lastModified() { + return 0; + } + + @Override + public char[] array() { + return array; + } + + + } + + private static class URLData implements Data { + private final URL url; + protected final Charset cs; + private int hash; + protected char[] array; + protected int length; + protected long lastModified; + + private URLData(final URL url, final Charset cs) { + this.url = Objects.requireNonNull(url); + this.cs = cs; + } + + @Override + public int hashCode() { + int h = hash; + if (h == 0) { + h = hash = url.hashCode(); + } + return h; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof URLData)) { + return false; + } + + URLData otherData = (URLData) other; + + if (url.equals(otherData.url)) { + // Make sure both have meta data loaded + try { + if (isDeferred()) { + // Data in cache is always loaded, and we only compare to cached data. + assert !otherData.isDeferred(); + loadMeta(); + } else if (otherData.isDeferred()) { + otherData.loadMeta(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + + // Compare meta data + return this.length == otherData.length && this.lastModified == otherData.lastModified; + } + return false; + } + + @Override + public String toString() { + return new String(array()); + } + + @Override + public URL url() { + return url; + } + + @Override + public int length() { + return length; + } + + @Override + public long lastModified() { + return lastModified; + } + + @Override + public char[] array() { + assert !isDeferred(); + return array; + } + + boolean isDeferred() { + return array == null; + } + + protected void checkPermissionAndClose() throws IOException { + try (InputStream in = url.openStream()) {} + debug("permission checked for ", url); + } + + protected void load() throws IOException { + if (array == null) { + final URLConnection c = url.openConnection(); + try (InputStream in = c.getInputStream()) { + array = cs == null ? readFully(in) : readFully(in, cs); + length = array.length; + lastModified = c.getLastModified(); + debug("loaded content for ", url); + } + } + } + + protected void loadMeta() throws IOException { + if (length == 0 && lastModified == 0) { + final URLConnection c = url.openConnection(); + length = c.getContentLength(); + lastModified = c.getLastModified(); + debug("loaded metadata for ", url); + } + } + } + + private static class FileData extends URLData { + private final File file; + + private FileData(final File file, final Charset cs) { + super(getURLFromFile(file), cs); + this.file = file; + + } + + @Override + protected void checkPermissionAndClose() throws IOException { + if (!file.canRead()) { + throw new FileNotFoundException(file + " (Permission Denied)"); + } + debug("permission checked for ", file); + } + + @Override + protected void loadMeta() { + if (length == 0 && lastModified == 0) { + length = (int) file.length(); + lastModified = file.lastModified(); + debug("loaded metadata for ", file); + } + } + + @Override + protected void load() throws IOException { + if (array == null) { + array = cs == null ? readFully(file) : readFully(file, cs); + length = array.length; + lastModified = file.lastModified(); + debug("loaded content for ", file); + } + } + } - private static final int BUFSIZE = 8 * 1024; + private static void debug(final Object... msg) { + DEBUG.info(msg); + } - // Do *not* make this public ever! Trusts the URL and content. So has to be called - // from other public constructors. Note that this can not be some init method as - // we initialize final fields from here. - private Source(final String name, final String base, final char[] content, final URL url) { - this.name = name; - this.base = base; - this.content = content; - this.length = content.length; - this.url = url; + private char[] data() { + return data.array(); } /** - * Constructor + * Returns an instance * * @param name source name * @param content contents as char array */ - public Source(final String name, final char[] content) { - this(name, baseName(name, null), content, null); + public static Source sourceFor(final String name, final char[] content) { + return new Source(name, baseName(name), new RawData(content)); } /** - * Constructor + * Returns an instance * * @param name source name * @param content contents as string */ - public Source(final String name, final String content) { - this(name, content.toCharArray()); + public static Source sourceFor(final String name, final String content) { + return new Source(name, baseName(name), new RawData(content)); } /** @@ -120,8 +383,8 @@ public final class Source { * * @throws IOException if source cannot be loaded */ - public Source(final String name, final URL url) throws IOException { - this(name, baseURL(url, null), readFully(url), url); + public static Source sourceFor(final String name, final URL url) throws IOException { + return sourceFor(name, url, null); } /** @@ -133,8 +396,8 @@ public final class Source { * * @throws IOException if source cannot be loaded */ - public Source(final String name, final URL url, final Charset cs) throws IOException { - this(name, baseURL(url, null), readFully(url, cs), url); + public static Source sourceFor(final String name, final URL url, final Charset cs) throws IOException { + return sourceFor(name, baseURL(url), new URLData(url, cs)); } /** @@ -145,8 +408,8 @@ public final class Source { * * @throws IOException if source cannot be loaded */ - public Source(final String name, final File file) throws IOException { - this(name, dirName(file, null), readFully(file), getURLFromFile(file)); + public static Source sourceFor(final String name, final File file) throws IOException { + return sourceFor(name, file, null); } /** @@ -158,8 +421,25 @@ public final class Source { * * @throws IOException if source cannot be loaded */ - public Source(final String name, final File file, final Charset cs) throws IOException { - this(name, dirName(file, null), readFully(file, cs), getURLFromFile(file)); + public static Source sourceFor(final String name, final File file, final Charset cs) throws IOException { + final File absFile = file.getAbsoluteFile(); + return sourceFor(name, dirName(absFile, null), new FileData(file, cs)); + } + + /** + * Returns an instance + * + * @param name source name + * @param reader reader from which source can be loaded + * @throws IOException if source cannot be loaded + */ + public static Source sourceFor(final String name, final Reader reader) throws IOException { + // Extract URL from URLReader to defer loading and reuse cached data if available. + if (reader instanceof URLReader) { + final URLReader urlReader = (URLReader) reader; + return sourceFor(name, urlReader.getURL(), urlReader.getCharset()); + } + return new Source(name, baseName(name), new RawData(reader)); } @Override @@ -167,21 +447,18 @@ public final class Source { if (this == obj) { return true; } - if (!(obj instanceof Source)) { return false; } - - final Source src = (Source)obj; - // Only compare content as a last resort measure - return length == src.length && Objects.equals(url, src.url) && Objects.equals(name, src.name) && Arrays.equals(content, src.content); + final Source other = (Source) obj; + return Objects.equals(name, other.name) && data.equals(other.data); } @Override public int hashCode() { int h = hash; if (h == 0) { - h = hash = Arrays.hashCode(content) ^ Objects.hashCode(name); + h = hash = data.hashCode() ^ Objects.hashCode(name); } return h; } @@ -191,7 +468,7 @@ public final class Source { * @return Source content. */ public String getString() { - return new String(content, 0, length); + return data.toString(); } /** @@ -203,6 +480,14 @@ public final class Source { } /** + * Get the last modified time of this script. + * @return Last modified time. + */ + public long getLastModified() { + return data.lastModified(); + } + + /** * Get the "directory" part of the file or "base" of the URL. * @return base of file or URL. */ @@ -217,7 +502,7 @@ public final class Source { * @return Source content portion. */ public String getString(final int start, final int len) { - return new String(content, start, len); + return new String(data(), start, len); } /** @@ -228,7 +513,7 @@ public final class Source { public String getString(final long token) { final int start = Token.descPosition(token); final int len = Token.descLength(token); - return new String(content, start, len); + return new String(data(), start, len); } /** @@ -238,7 +523,7 @@ public final class Source { * @return URL source or null */ public URL getURL() { - return url; + return data.url(); } /** @@ -247,8 +532,9 @@ public final class Source { * @return Index of first character of line. */ private int findBOLN(final int position) { + final char[] data = data(); for (int i = position - 1; i > 0; i--) { - final char ch = content[i]; + final char ch = data[i]; if (ch == '\n' || ch == '\r') { return i + 1; @@ -264,8 +550,10 @@ public final class Source { * @return Index of last character of line. */ private int findEOLN(final int position) { - for (int i = position; i < length; i++) { - final char ch = content[i]; + final char[] data = data(); + final int length = data.length; + for (int i = position; i < length; i++) { + final char ch = data[i]; if (ch == '\n' || ch == '\r') { return i - 1; @@ -285,11 +573,12 @@ public final class Source { * @return Line number. */ public int getLine(final int position) { + final char[] data = data(); // Line count starts at 1. int line = 1; for (int i = 0; i < position; i++) { - final char ch = content[i]; + final char ch = data[i]; // Works for both \n and \r\n. if (ch == '\n') { line++; @@ -320,7 +609,7 @@ public final class Source { // Find end of this line. final int last = findEOLN(position); - return new String(content, first, last - first + 1); + return new String(data(), first, last - first + 1); } /** @@ -328,7 +617,7 @@ public final class Source { * @return content */ public char[] getContent() { - return content.clone(); + return data().clone(); } /** @@ -336,19 +625,18 @@ public final class Source { * @return length */ public int getLength() { - return length; + return data.length(); } /** * Read all of the source until end of file. Return it as char array * - * @param reader reader opened to source stream + * @param reader reader opened to source stream * @return source as content - * * @throws IOException if source could not be read */ public static char[] readFully(final Reader reader) throws IOException { - final char[] arr = new char[BUFSIZE]; + final char[] arr = new char[BUF_SIZE]; final StringBuilder sb = new StringBuilder(); try { @@ -366,9 +654,8 @@ public final class Source { /** * Read all of the source until end of file. Return it as char array * - * @param file source file + * @param file source file * @return source as content - * * @throws IOException if source could not be read */ public static char[] readFully(final File file) throws IOException { @@ -381,10 +668,9 @@ public final class Source { /** * Read all of the source until end of file. Return it as char array * - * @param file source file + * @param file source file * @param cs Charset used to convert bytes to chars * @return source as content - * * @throws IOException if source could not be read */ public static char[] readFully(final File file, final Charset cs) throws IOException { @@ -393,7 +679,7 @@ public final class Source { } final byte[] buf = Files.readAllBytes(file.toPath()); - return (cs != null)? new String(buf, cs).toCharArray() : byteToCharArray(buf); + return (cs != null) ? new String(buf, cs).toCharArray() : byteToCharArray(buf); } /** @@ -401,7 +687,6 @@ public final class Source { * * @param url URL to read content from * @return source as content - * * @throws IOException if source could not be read */ public static char[] readFully(final URL url) throws IOException { @@ -414,7 +699,6 @@ public final class Source { * @param url URL to read content from * @param cs Charset used to convert bytes to chars * @return source as content - * * @throws IOException if source could not be read */ public static char[] readFully(final URL url, final Charset cs) throws IOException { @@ -428,7 +712,7 @@ public final class Source { */ public synchronized byte[] getDigest() { if (digest == null) { - + final char[] content = data(); final byte[] bytes = new byte[content.length * 2]; for (int i = 0; i < content.length; i++) { @@ -444,8 +728,8 @@ public final class Source { if (base != null) { md.update(base.getBytes(StandardCharsets.UTF_8)); } - if (url != null) { - md.update(url.toString().getBytes(StandardCharsets.UTF_8)); + if (getURL() != null) { + md.update(getURL().toString().getBytes(StandardCharsets.UTF_8)); } digest = md.digest(bytes); } catch (NoSuchAlgorithmException e) { @@ -461,50 +745,46 @@ public final class Source { * @return base URL for url */ public static String baseURL(final URL url) { - return baseURL(url, null); - } - - private static String baseURL(final URL url, final String defaultValue) { if (url.getProtocol().equals("file")) { try { final Path path = Paths.get(url.toURI()); final Path parent = path.getParent(); - return (parent != null) ? (parent + File.separator) : defaultValue; + return (parent != null) ? (parent + File.separator) : null; } catch (final SecurityException | URISyntaxException | IOError e) { - return defaultValue; + return null; } } // FIXME: is there a better way to find 'base' URL of a given URL? String path = url.getPath(); if (path.isEmpty()) { - return defaultValue; + return null; } path = path.substring(0, path.lastIndexOf('/') + 1); final int port = url.getPort(); try { return new URL(url.getProtocol(), url.getHost(), port, path).toString(); } catch (final MalformedURLException e) { - return defaultValue; + return null; } } - private static String dirName(final File file, final String defaultValue) { + private static String dirName(final File file, final String DEFAULT_BASE_NAME) { final String res = file.getParent(); - return (res != null)? (res + File.separator) : defaultValue; + return (res != null) ? (res + File.separator) : DEFAULT_BASE_NAME; } // fake directory like name - private static String baseName(final String name, final String defaultValue) { + private static String baseName(final String name) { int idx = name.lastIndexOf('/'); if (idx == -1) { idx = name.lastIndexOf('\\'); } - return (idx != -1)? name.substring(0, idx + 1) : defaultValue; + return (idx != -1) ? name.substring(0, idx + 1) : null; } private static char[] readFully(final InputStream is, final Charset cs) throws IOException { - return (cs != null)? new String(readBytes(is), cs).toCharArray() : readFully(is); + return (cs != null) ? new String(readBytes(is), cs).toCharArray() : readFully(is); } private static char[] readFully(final InputStream is) throws IOException { @@ -515,19 +795,19 @@ public final class Source { Charset cs = StandardCharsets.UTF_8; int start = 0; // BOM detection. - if (bytes.length > 1 && bytes[0] == (byte)0xFE && bytes[1] == (byte)0xFF) { + if (bytes.length > 1 && bytes[0] == (byte) 0xFE && bytes[1] == (byte) 0xFF) { start = 2; cs = StandardCharsets.UTF_16BE; - } else if (bytes.length > 1 && bytes[0] == (byte)0xFF && bytes[1] == (byte)0xFE) { + } else if (bytes.length > 1 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE) { start = 2; cs = StandardCharsets.UTF_16LE; - } else if (bytes.length > 2 && bytes[0] == (byte)0xEF && bytes[1] == (byte)0xBB && bytes[2] == (byte)0xBF) { + } else if (bytes.length > 2 && bytes[0] == (byte) 0xEF && bytes[1] == (byte) 0xBB && bytes[2] == (byte) 0xBF) { start = 3; cs = StandardCharsets.UTF_8; - } else if (bytes.length > 3 && bytes[0] == (byte)0xFF && bytes[1] == (byte)0xFE && bytes[2] == 0 && bytes[3] == 0) { + } else if (bytes.length > 3 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE && bytes[2] == 0 && bytes[3] == 0) { start = 4; cs = Charset.forName("UTF-32LE"); - } else if (bytes.length > 3 && bytes[0] == 0 && bytes[1] == 0 && bytes[2] == (byte)0xFE && bytes[3] == (byte)0xFF) { + } else if (bytes.length > 3 && bytes[0] == 0 && bytes[1] == 0 && bytes[2] == (byte) 0xFE && bytes[3] == (byte) 0xFF) { start = 4; cs = Charset.forName("UTF-32BE"); } @@ -536,7 +816,7 @@ public final class Source { } static byte[] readBytes(final InputStream is) throws IOException { - final byte[] arr = new byte[BUFSIZE]; + final byte[] arr = new byte[BUF_SIZE]; try { try (ByteArrayOutputStream buf = new ByteArrayOutputStream()) { int numBytes; diff --git a/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java b/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java index 9250331d..f5158021 100644 --- a/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java +++ b/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java @@ -46,9 +46,6 @@ public class JdkRegExp extends RegExp { /** Java regexp pattern to use for match. We compile to one of these */ private Pattern pattern; - /** The matcher */ - private RegExpMatcher matcher; - /** * Construct a Regular expression from the given {@code source} and {@code flags} strings. * @@ -95,14 +92,7 @@ public class JdkRegExp extends RegExp { return null; // never matches or similar, e.g. a[] } - RegExpMatcher currentMatcher = this.matcher; - - if (currentMatcher == null || matcher.getInput() != str) { - currentMatcher = new DefaultMatcher(str); - this.matcher = currentMatcher; - } - - return currentMatcher; + return new DefaultMatcher(str); } class DefaultMatcher implements RegExpMatcher { diff --git a/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java b/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java index 5ff98ac5..47dbd7c4 100644 --- a/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java +++ b/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java @@ -44,9 +44,6 @@ public class JoniRegExp extends RegExp { /** Compiled Joni Regex */ private Regex regex; - /** Matcher */ - private RegExpMatcher matcher; - /** * Construct a Regular expression from the given {@code pattern} and {@code flags} strings. * @@ -95,14 +92,7 @@ public class JoniRegExp extends RegExp { return null; } - RegExpMatcher currentMatcher = this.matcher; - - if (currentMatcher == null || input != currentMatcher.getInput()) { - currentMatcher = new JoniMatcher(input); - this.matcher = currentMatcher; - } - - return currentMatcher; + return new JoniMatcher(input); } /** diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java index 360c11eb..91117d1d 100644 --- a/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java @@ -131,12 +131,13 @@ public final class Regex implements RegexState { this.warnings = null; } - public void compile() { + public synchronized MatcherFactory compile() { if (factory == null && analyser != null) { - Compiler compiler = new ArrayCompiler(analyser); + new ArrayCompiler(analyser).compile(); analyser = null; // only do this once - compiler.compile(); } + assert factory != null; + return factory; } public Matcher matcher(char[] chars) { @@ -144,8 +145,11 @@ public final class Regex implements RegexState { } public Matcher matcher(char[] chars, int p, int end) { - compile(); - return factory.create(this, chars, p, end); + MatcherFactory matcherFactory = factory; + if (matcherFactory == null) { + matcherFactory = compile(); + } + return matcherFactory.create(this, chars, p, end); } public WarnCallback getWarnings() { diff --git a/src/jdk/nashorn/internal/runtime/resources/Options.properties b/src/jdk/nashorn/internal/runtime/resources/Options.properties index 033fcc25..9262a401 100644 --- a/src/jdk/nashorn/internal/runtime/resources/Options.properties +++ b/src/jdk/nashorn/internal/runtime/resources/Options.properties @@ -102,6 +102,13 @@ nashorn.option.compile.only = { \ type=Boolean \ } +nashorn.option.const.as.var = { \ + name="--const-as-var", \ + is_undocumented=true, \ + desc="Replace 'const' with 'var'.", \ + type=Boolean \ +} + nashorn.option.d = { \ name="--dump-debug-dir", \ short_name="-d", \ diff --git a/src/jdk/nashorn/tools/Shell.java b/src/jdk/nashorn/tools/Shell.java index ad833d81..33e0afd7 100644 --- a/src/jdk/nashorn/tools/Shell.java +++ b/src/jdk/nashorn/tools/Shell.java @@ -25,6 +25,8 @@ package jdk.nashorn.tools; +import static jdk.nashorn.internal.runtime.Source.sourceFor; + import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -50,7 +52,6 @@ import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.Property; import jdk.nashorn.internal.runtime.ScriptEnvironment; import jdk.nashorn.internal.runtime.ScriptFunction; -import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.Source; import jdk.nashorn.internal.runtime.options.Options; @@ -244,7 +245,7 @@ public class Shell { // For each file on the command line. for (final String fileName : files) { - final FunctionNode functionNode = new Parser(env, new Source(fileName, new File(fileName)), errors).parse(); + final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors).parse(); if (errors.getNumberOfErrors() != 0) { return COMPILATION_ERROR; @@ -302,7 +303,7 @@ public class Shell { } final File file = new File(fileName); - final ScriptFunction script = context.compileScript(new Source(fileName, file.toURI().toURL()), global); + final ScriptFunction script = context.compileScript(sourceFor(fileName, file), global); if (script == null || errors.getNumberOfErrors() != 0) { return COMPILATION_ERROR; } @@ -405,7 +406,7 @@ public class Shell { // initialize with "shell.js" script try { - final Source source = new Source("<shell.js>", Shell.class.getResource("resources/shell.js")); + final Source source = sourceFor("<shell.js>", Shell.class.getResource("resources/shell.js")); context.eval(global, source.getString(), global, "<shell.js>", false); } catch (final Exception e) { err.println(e); @@ -452,7 +453,7 @@ public class Shell { } } finally { if (globalChanged) { - Context.setGlobal(global); + Context.setGlobal(oldGlobal); } } diff --git a/test/script/basic/JDK-8008448.js b/test/script/basic/JDK-8008448.js index b30e3417..240efd61 100644 --- a/test/script/basic/JDK-8008448.js +++ b/test/script/basic/JDK-8008448.js @@ -26,6 +26,7 @@ * Ensure that all parseable files can be parsed using parser API. * * @test + * @option --const-as-var * @option -scripting * @run */ diff --git a/test/script/basic/JDK-8024120.js b/test/script/basic/JDK-8024120.js index 0ac4ff98..d2913d52 100644 --- a/test/script/basic/JDK-8024120.js +++ b/test/script/basic/JDK-8024120.js @@ -32,10 +32,6 @@ var obj = {}; obj.__proto__ = null; -if (obj.__proto__ !== null || typeof(obj.__proto__) != 'object') { - fail("obj.__proto__ is expected to be null"); -} - var p = Object.getPrototypeOf(obj); if (p !== null || typeof(p) != 'object') { fail("Object.getPrototypeOf(obj) is expected to be null"); diff --git a/test/script/basic/JDK-8024174.js b/test/script/basic/JDK-8024174.js index 5fd48e17..bd9206a6 100644 --- a/test/script/basic/JDK-8024174.js +++ b/test/script/basic/JDK-8024174.js @@ -46,6 +46,6 @@ var obj2 = { __proto__: null }; -if (obj2.__proto__ !== null || Object.getPrototypeOf(obj2) !== null) { +if (Object.getPrototypeOf(obj2) !== null) { fail("obj2.__proto__ was not set to null inside literal"); } diff --git a/test/script/basic/JDK-8026161.js b/test/script/basic/JDK-8026161.js index 49f888b7..e3e88486 100644 --- a/test/script/basic/JDK-8026161.js +++ b/test/script/basic/JDK-8026161.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,5 +28,5 @@ * @run */ -print(new java.awt.Color(1, 1, 1)) // creates Color[r=1,g=1,b=1] -print(new java.awt.Color(1.0, 1.0, 1.0)) // Color[r=255,g=255,b=255] +print(Java.type("jdk.nashorn.test.models.IntFloatOverloadSelection").overloadedMethod(1)) +print(Java.type("jdk.nashorn.test.models.IntFloatOverloadSelection").overloadedMethod(1.0)) diff --git a/test/script/basic/JDK-8026161.js.EXPECTED b/test/script/basic/JDK-8026161.js.EXPECTED index c7b00b08..ac032cff 100644 --- a/test/script/basic/JDK-8026161.js.EXPECTED +++ b/test/script/basic/JDK-8026161.js.EXPECTED @@ -1,2 +1,2 @@ -java.awt.Color[r=1,g=1,b=1] -java.awt.Color[r=255,g=255,b=255] +int +float diff --git a/test/script/basic/JDK-8027933.js b/test/script/basic/JDK-8027933.js new file mode 100644 index 00000000..506abc23 --- /dev/null +++ b/test/script/basic/JDK-8027933.js @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8027933: Add const.as.var option + * + * @test + * @option --const-as-var + * @run + */ + +const THE_ANSWER = 42; +print("Answer to all questions: " + THE_ANSWER); + +print((function () { + const FORTY_TWO = 42; + return FORTY_TWO +})()) diff --git a/test/script/basic/JDK-8027933.js.EXPECTED b/test/script/basic/JDK-8027933.js.EXPECTED new file mode 100644 index 00000000..cb920ab6 --- /dev/null +++ b/test/script/basic/JDK-8027933.js.EXPECTED @@ -0,0 +1,2 @@ +Answer to all questions: 42 +42 diff --git a/test/script/basic/JDK-8041998.js b/test/script/basic/JDK-8041998.js new file mode 100644 index 00000000..33e4d136 --- /dev/null +++ b/test/script/basic/JDK-8041998.js @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8041998: RegExp implementation is not thread-safe + * + * @test + * @run + */ + +var Thread = java.lang.Thread; + +function run() { + var line = 'content-type: text/html'; + for (var i = 0; i < 300; i++) { + Thread.sleep(1); + line.split(/: /); + } + print("done"); +} + +var threads = []; + +for (var i = 0; i < 4; i++) { + var thread = new Thread(run); + thread.start(); + threads.push(thread); +} + +for (var i = 0; i < 4; i++) { + threads[i].join(); +} diff --git a/test/script/basic/JDK-8041998.js.EXPECTED b/test/script/basic/JDK-8041998.js.EXPECTED new file mode 100644 index 00000000..8f92fbfa --- /dev/null +++ b/test/script/basic/JDK-8041998.js.EXPECTED @@ -0,0 +1,4 @@ +done +done +done +done diff --git a/test/script/basic/JDK-8042364.js b/test/script/basic/JDK-8042364.js new file mode 100644 index 00000000..d8b81e24 --- /dev/null +++ b/test/script/basic/JDK-8042364.js @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8042364: Make __proto__ ES6 draft compliant + * + * @test + * @run + */ + +// check for Object.prototype.__proto__ accessor property +print("Object.prototype has __proto__?", + Object.prototype.hasOwnProperty("__proto__")) + +var desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__") +print("descriptor"); +print(JSON.stringify(desc)) +print("getter", desc.get) +print("setter", desc.set) + +// no computed "__proto__" name, only identifier! +var p = {} +var obj = { + "__proto__" : p +} + +if (Object.getPrototypeOf(obj) === p) { + fail("obj has wrong __proto__, allows computed __proto__!") +} + +if (obj.__proto__ !== p) { + fail("__proto__ not created as normal property!") +} + +if (Object.getPrototypeOf(obj) !== Object.prototype) { + fail("obj has wrong __proto__") +} + +var obj2 = { + __proto__: p +} + +if (Object.getPrototypeOf(obj2) !== p) { + fail("can't set __proto__ in object literal") +} diff --git a/test/script/basic/JDK-8042364.js.EXPECTED b/test/script/basic/JDK-8042364.js.EXPECTED new file mode 100644 index 00000000..b92947a8 --- /dev/null +++ b/test/script/basic/JDK-8042364.js.EXPECTED @@ -0,0 +1,5 @@ +Object.prototype has __proto__? true +descriptor +{"configurable":true,"enumerable":false} +getter function getProto() { [native code] } +setter function setProto() { [native code] } diff --git a/test/script/error/JDK-8027933.js b/test/script/error/JDK-8027933.js new file mode 100644 index 00000000..9b398fa5 --- /dev/null +++ b/test/script/error/JDK-8027933.js @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8027933: Add const.as.var option + * + * @test/compile-error + */ + +// without --const-as-var the following should fail to compile +const THE_ANSWER = 42; diff --git a/test/script/error/JDK-8027933.js.EXPECTED b/test/script/error/JDK-8027933.js.EXPECTED new file mode 100644 index 00000000..9389a5fc --- /dev/null +++ b/test/script/error/JDK-8027933.js.EXPECTED @@ -0,0 +1,3 @@ +test/script/error/JDK-8027933.js:31:0 Expected an operand but found const +const THE_ANSWER = 42; +^ diff --git a/test/script/trusted/JDK-8006529.js b/test/script/trusted/JDK-8006529.js index 8eb83909..3567c33e 100644 --- a/test/script/trusted/JDK-8006529.js +++ b/test/script/trusted/JDK-8006529.js @@ -113,7 +113,7 @@ function findFunction(node) { var getContextMethod = Context.class.getMethod("getContext") var getEnvMethod = Context.class.getMethod("getEnv") -var SourceConstructor = Source.class.getConstructor(java.lang.String.class, java.lang.String.class) +var sourceForMethod = Source.class.getMethod("sourceFor", java.lang.String.class, java.lang.String.class) var ParserConstructor = Parser.class.getConstructor(ScriptEnvironment.class, Source.class, ErrorManager.class) var CompilerConstructor = Compiler.class.getConstructor(ScriptEnvironment.class) @@ -121,7 +121,7 @@ var CompilerConstructor = Compiler.class.getConstructor(ScriptEnvironment.class) // source code, returns a jdk.nashorn.internal.ir.FunctionNode object // representing it. function compile(source) { - var source = SourceConstructor.newInstance("<no name>", source); + var source = sourceForMethod.invoke(null, "<no name>", source); var env = getEnvMethod.invoke(getContextMethod.invoke(null)) diff --git a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java index ac438101..1ebb97a2 100644 --- a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java +++ b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java @@ -25,6 +25,9 @@ package jdk.nashorn.internal.codegen; +import static jdk.nashorn.internal.runtime.Source.sourceFor; +import static jdk.nashorn.internal.runtime.Source.readFully; + import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; @@ -32,7 +35,6 @@ import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ErrorManager; import jdk.nashorn.internal.runtime.ScriptFunction; -import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.Source; import jdk.nashorn.internal.runtime.options.Options; import org.testng.Assert; @@ -69,6 +71,7 @@ public class CompilerTest { options.set("print.ast", true); options.set("print.parse", true); options.set("scripting", true); + options.set("const.as.var", true); final ErrorManager errors = new ErrorManager() { @Override @@ -151,7 +154,7 @@ public class CompilerTest { final boolean globalChanged = (oldGlobal != global); try { - final char[] buffer = Source.readFully(file); + final char[] buffer = readFully(file); boolean excluded = false; if (filter != null) { @@ -170,7 +173,7 @@ public class CompilerTest { if (globalChanged) { Context.setGlobal(global); } - final Source source = new Source(file.getAbsolutePath(), buffer); + final Source source = sourceFor(file.getAbsolutePath(), buffer); final ScriptFunction script = context.compileScript(source, global); if (script == null || context.getErrorManager().getNumberOfErrors() > 0) { log("Compile failed: " + file.getAbsolutePath()); diff --git a/test/src/jdk/nashorn/internal/parser/ParserTest.java b/test/src/jdk/nashorn/internal/parser/ParserTest.java index 3e10a89e..8a68bb11 100644 --- a/test/src/jdk/nashorn/internal/parser/ParserTest.java +++ b/test/src/jdk/nashorn/internal/parser/ParserTest.java @@ -25,6 +25,9 @@ package jdk.nashorn.internal.parser; +import static jdk.nashorn.internal.runtime.Source.sourceFor; +import static jdk.nashorn.internal.runtime.Source.readFully; + import java.io.File; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ErrorManager; @@ -62,6 +65,7 @@ public class ParserTest { options.set("anon.functions", true); options.set("parse.only", true); options.set("scripting", true); + options.set("const.as.var", true); ErrorManager errors = new ErrorManager(); this.context = new Context(options, errors, Thread.currentThread().getContextClassLoader()); @@ -131,7 +135,7 @@ public class ParserTest { } try { - final char[] buffer = Source.readFully(file); + final char[] buffer = readFully(file); boolean excluded = false; if (filter != null) { final String content = new String(buffer); @@ -153,7 +157,7 @@ public class ParserTest { } }; errors.setLimit(0); - final Source source = new Source(file.getAbsolutePath(), buffer); + final Source source = sourceFor(file.getAbsolutePath(), buffer); new Parser(context.getEnv(), source, errors).parse(); if (errors.getNumberOfErrors() > 0) { log("Parse failed: " + file.getAbsolutePath()); diff --git a/test/src/jdk/nashorn/internal/runtime/ContextTest.java b/test/src/jdk/nashorn/internal/runtime/ContextTest.java index 1ec41695..4c4a8c65 100644 --- a/test/src/jdk/nashorn/internal/runtime/ContextTest.java +++ b/test/src/jdk/nashorn/internal/runtime/ContextTest.java @@ -25,6 +25,7 @@ package jdk.nashorn.internal.runtime; +import static jdk.nashorn.internal.runtime.Source.sourceFor; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @@ -107,7 +108,7 @@ public class ContextTest { } private Object eval(final Context cx, final String name, final String code) { - final Source source = new Source(name, code); + final Source source = sourceFor(name, code); final ScriptObject global = Context.getGlobal(); final ScriptFunction func = cx.compileScript(source, global); return func != null ? ScriptRuntime.apply(func, global) : null; diff --git a/test/src/jdk/nashorn/internal/runtime/SourceTest.java b/test/src/jdk/nashorn/internal/runtime/SourceTest.java new file mode 100644 index 00000000..34635856 --- /dev/null +++ b/test/src/jdk/nashorn/internal/runtime/SourceTest.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.runtime; + +import jdk.nashorn.api.scripting.URLReader; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URL; +import java.util.Arrays; + +import static jdk.nashorn.internal.runtime.Source.sourceFor; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +/** + * Tests different Source representations. + */ +public class SourceTest { + + final private static String SOURCE_NAME = "source.js"; + final private static String SOURCE_STRING = "var x = 1;"; + final private static char[] SOURCE_CHARS = SOURCE_STRING.toCharArray(); + final private static String RESOURCE_PATH = "resources/load_test.js"; + final private static File SOURCE_FILE = new File("build/test/classes/jdk/nashorn/internal/runtime/" + RESOURCE_PATH); + final private static URL SOURCE_URL = SourceTest.class.getResource(RESOURCE_PATH); + + + @Test + public void testStringSource() { + testSources(sourceFor(SOURCE_NAME, SOURCE_STRING), sourceFor(SOURCE_NAME, SOURCE_STRING)); + testSources(sourceFor(SOURCE_NAME, SOURCE_STRING), sourceFor(SOURCE_NAME, SOURCE_CHARS)); + } + + @Test + public void testCharArraySource() { + testSources(sourceFor(SOURCE_NAME, SOURCE_CHARS), sourceFor(SOURCE_NAME, SOURCE_CHARS)); + testSources(sourceFor(SOURCE_NAME, SOURCE_CHARS), sourceFor(SOURCE_NAME, SOURCE_STRING)); + } + + @Test + public void testURLSource() { + try { + testSources(sourceFor(SOURCE_NAME, SOURCE_URL), sourceFor(SOURCE_NAME, SOURCE_URL)); + testSources(sourceFor(SOURCE_NAME, SOURCE_URL), sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL))); + + } catch (final IOException e) { + fail(e.toString()); + } + } + + @Test + public void testURLReaderSource() { + try { + System.err.println(SourceTest.class.getResource("")); + testSources(sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL)), sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL))); + testSources(sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL)), sourceFor(SOURCE_NAME, SOURCE_URL)); + } catch (final IOException e) { + fail(e.toString()); + } + } + + @Test + public void testReaderSource() { + try { + testSources(sourceFor(SOURCE_NAME, getReader(RESOURCE_PATH)), sourceFor(SOURCE_NAME, getReader(RESOURCE_PATH))); + } catch (final IOException e) { + fail(e.toString()); + } + } + + @Test + public void testFileSource() { + try { + testSources(sourceFor(SOURCE_NAME, SOURCE_FILE), sourceFor(SOURCE_NAME, SOURCE_FILE)); + } catch (final IOException e) { + fail(e.toString()); + } + } + + private Reader getReader(final String path) { + return new InputStreamReader(SourceTest.class.getResourceAsStream(path)); + } + + private void testSources(final Source source1, final Source source2) { + final char[] chars1 = source1.getContent(); + final char[] chars2 = source2.getContent(); + final String str1 = source1.getString(); + final String str2 = source2.getString(); + assertTrue(Arrays.equals(chars1, chars2)); + assertEquals(str1, str2); + assertEquals(source1.hashCode(), source2.hashCode()); + assertTrue(source1.equals(source2)); + // Test for immutability + Arrays.fill(source1.getContent(), (char)0); + Arrays.fill(source2.getContent(), (char)1); + assertTrue(Arrays.equals(source1.getContent(), str1.toCharArray())); + assertTrue(Arrays.equals(source1.getContent(), chars1)); + assertTrue(Arrays.equals(source1.getContent(), source2.getContent())); + } +} diff --git a/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java b/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java index 469d890e..f6da6f82 100644 --- a/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java +++ b/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java @@ -220,4 +220,19 @@ public class TrustedScriptEngineTest { // bar should be visible in default context assertTrue(e.eval("typeof bar").equals("function")); } + + + @Test public void nashornSwallowsConstKeyword() throws Exception { + final NashornScriptEngineFactory f = new NashornScriptEngineFactory(); + final String[] args = new String[] { "--const-as-var" }; + final ScriptEngine engine = f.getScriptEngine(args); + + final Object ret = engine.eval("" + + "(function() {\n" + + " const x = 10;\n" + + " return x;\n" + + "})();" + ); + assertEquals(ret, 10, "Parsed and executed OK"); + } } diff --git a/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java b/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java index 83d057f3..47ea7b32 100644 --- a/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java +++ b/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java @@ -25,6 +25,7 @@ package jdk.nashorn.internal.test.framework; +import static jdk.nashorn.internal.runtime.Source.sourceFor; import static jdk.nashorn.tools.Shell.COMPILATION_ERROR; import static jdk.nashorn.tools.Shell.RUNTIME_ERROR; import static jdk.nashorn.tools.Shell.SUCCESS; @@ -39,7 +40,6 @@ import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ErrorManager; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptRuntime; -import jdk.nashorn.internal.runtime.Source; import jdk.nashorn.internal.runtime.options.Options; /** @@ -125,7 +125,7 @@ public final class SharedContextEvaluator implements ScriptEvaluator { continue; } final File file = new File(fileName); - ScriptFunction script = context.compileScript(new Source(fileName, file.toURI().toURL()), global); + ScriptFunction script = context.compileScript(sourceFor(fileName, file.toURI().toURL()), global); if (script == null || errors.getNumberOfErrors() != 0) { return COMPILATION_ERROR; diff --git a/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java b/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java new file mode 100644 index 00000000..947896b3 --- /dev/null +++ b/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.nashorn.test.models; + +public class IntFloatOverloadSelection { + + public static String overloadedMethod(int i) { + return "int"; + } + + public static String overloadedMethod(float f) { + return "float"; + } +} diff --git a/test/src/jdk/nashorn/test/models/SourceHelper.java b/test/src/jdk/nashorn/test/models/SourceHelper.java index 46b1e488..7e90f304 100644 --- a/test/src/jdk/nashorn/test/models/SourceHelper.java +++ b/test/src/jdk/nashorn/test/models/SourceHelper.java @@ -46,7 +46,7 @@ public final class SourceHelper { } public static String readFully(final URL url) throws IOException { - return new Source(url.toString(), url).getString(); + return Source.sourceFor(url.toString(), url).getString(); } public static String readFully(final Reader reader) throws IOException { |