From 6baef4dae7b691c875d80319c22e84d3e2050621 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Tue, 28 Mar 2023 00:57:47 -0400 Subject: [PATCH] nashorn --- .../01-installation/01-standalone.mdx | 2 +- .../01-installation/07-bun.md | 16 +- docz/docs/03-demos/01-frontend/01-react.md | 2 +- docz/docs/03-demos/01-frontend/02-vue.md | 2 +- docz/docs/03-demos/01-frontend/03-angular.md | 2 +- docz/docs/03-demos/01-frontend/04-svelte.md | 2 +- docz/docs/03-demos/12-engines/04_nashorn.md | 204 ++++++++++++++++++ docz/docs/03-demos/12-engines/index.md | 103 +-------- docz/static/nashorn/SheetJSNashorn.java | 37 ++++ 9 files changed, 260 insertions(+), 110 deletions(-) create mode 100644 docz/docs/03-demos/12-engines/04_nashorn.md create mode 100644 docz/static/nashorn/SheetJSNashorn.java diff --git a/docz/docs/02-getting-started/01-installation/01-standalone.mdx b/docz/docs/02-getting-started/01-installation/01-standalone.mdx index a0c63c4..f405443 100644 --- a/docz/docs/02-getting-started/01-installation/01-standalone.mdx +++ b/docz/docs/02-getting-started/01-installation/01-standalone.mdx @@ -161,7 +161,7 @@ Bower is deprecated and the maintainers recommend using other tools. ::: -[Bower](https://bower.io/) plays nice with the CDN tarballs: +The Bower package manager plays nice with the CDN tarballs:
{`\
 npx bower install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
diff --git a/docz/docs/02-getting-started/01-installation/07-bun.md b/docz/docs/02-getting-started/01-installation/07-bun.md
index a787e9e..9ea3106 100644
--- a/docz/docs/02-getting-started/01-installation/07-bun.md
+++ b/docz/docs/02-getting-started/01-installation/07-bun.md
@@ -10,15 +10,6 @@ import current from '/version.js';
 
 # Bun
 
-[Bun](https://bun.sh/) is a JavaScript runtime powered by JavaScriptCore.
-
-:::caution Bun support is considered experimental.
-
-Great open source software grows with user tests and reports. Any issues should
-be reported to the Bun project for further diagnosis.
-
-:::
-
 Each standalone release script is available at .
 
 
https://cdn.sheetjs.com/xlsx-{current}/package/xlsx.mjs is the URL for {current}

@@ -31,6 +22,13 @@ import * as fs from 'fs'; XLSX.set_fs(fs); ``` +:::caution Bun support is considered experimental. + +Great open source software grows with user tests and reports. Any issues should +be reported to the Bun project for further diagnosis. + +::: + ## Encoding support If Encoding support is required, `cpexcel.full.mjs` must be manually imported. diff --git a/docz/docs/03-demos/01-frontend/01-react.md b/docz/docs/03-demos/01-frontend/01-react.md index 4f54ac3..e8faef4 100644 --- a/docz/docs/03-demos/01-frontend/01-react.md +++ b/docz/docs/03-demos/01-frontend/01-react.md @@ -5,7 +5,7 @@ pagination_next: demos/grid/index sidebar_position: 1 --- -[ReactJS](https://reactjs.org/) is a JS library for building user interfaces. +ReactJS is a JS library for building user interfaces. This demo tries to cover common React data flow ideas and strategies. React familiarity is assumed. diff --git a/docz/docs/03-demos/01-frontend/02-vue.md b/docz/docs/03-demos/01-frontend/02-vue.md index b57de51..2217a40 100644 --- a/docz/docs/03-demos/01-frontend/02-vue.md +++ b/docz/docs/03-demos/01-frontend/02-vue.md @@ -5,7 +5,7 @@ pagination_next: demos/grid/index sidebar_position: 2 --- -[VueJS](https://vuejs.org/) is a JS library for building user interfaces. +VueJS is a JS library for building user interfaces. This demo covers common VueJS data flow ideas and strategies. Single-File Components (SFC) and VueJS familiarity is assumed. diff --git a/docz/docs/03-demos/01-frontend/03-angular.md b/docz/docs/03-demos/01-frontend/03-angular.md index 9b60475..255ec10 100644 --- a/docz/docs/03-demos/01-frontend/03-angular.md +++ b/docz/docs/03-demos/01-frontend/03-angular.md @@ -8,7 +8,7 @@ sidebar_position: 3 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -[Angular](https://angular.io/) is a JS library for building user interfaces. +Angular is a JS library for building user interfaces. This demo tries to cover common Angular data flow ideas and strategies. Angular and TypeScript familiarity is assumed. diff --git a/docz/docs/03-demos/01-frontend/04-svelte.md b/docz/docs/03-demos/01-frontend/04-svelte.md index c183871..e7f60d3 100644 --- a/docz/docs/03-demos/01-frontend/04-svelte.md +++ b/docz/docs/03-demos/01-frontend/04-svelte.md @@ -5,7 +5,7 @@ pagination_next: demos/grid/index sidebar_position: 4 --- -[Svelte](https://svelte.dev/) is a JS library for building user interfaces. +Svelte is a JS library for building user interfaces. This demo tries to cover common Svelte data flow ideas and strategies. Svelte familiarity is assumed. diff --git a/docz/docs/03-demos/12-engines/04_nashorn.md b/docz/docs/03-demos/12-engines/04_nashorn.md new file mode 100644 index 0000000..6363edc --- /dev/null +++ b/docz/docs/03-demos/12-engines/04_nashorn.md @@ -0,0 +1,204 @@ +--- +title: Java + Nashorn +pagination_prev: demos/bigdata/index +pagination_next: solutions/input +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +Nashorn is a JavaScript engine for Java. It shipped with Java distributions +starting with Java 8 and was eventually removed in Java 15. The project was +spun off and a compatible standalone release is available for Java 15+. + +The [Standalone scripts](/docs/getting-started/installation/standalone) can be +parsed and evaluated in a Nashorn context. + +## Integration Details + +_Initialize Nashorn_ + +`global` must be created from a Nashorn engine: + +```java +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Scanner; + +/* initialize nashorn engine */ +ScriptEngine engine = (new ScriptEngineManager()).getEngineByName("javascript"); + +/* create global */ +engine.eval("var global = (function(){ return this; }).call(null);"); +``` + +_Load SheetJS Scripts_ + +The main library can be loaded by reading the script from the file system and +evaluating in the Nashorn context: + +```java +engine.eval(new Scanner( + SheetJS.class.getResourceAsStream("/xlsx.full.min.js") +).useDelimiter("\\Z").next()); +``` + +To confirm the library is loaded, `XLSX.version` can be printed using the +Nashorn `print` built-in: + +```java +engine.eval("print('SheetJS Version ' + XLSX.version);"); +``` + +### Reading Files + +Nashorn does not properly project `byte[]` into a JS array or `Int8Array`. The +recommended workaround is to copy the data in the JS context using the JS code: + +```js +function b2a(b) { + var out = typeof Uint8Array == 'function' ? new Uint8Array(b.length) : new Array(b.length); + /* `b` is similar to Int8Array (values in the range -128 .. 127 ) */ + for(var i = 0; i < out.length; i++) out[i] = (b[i] + 256) & 0xFF; + return out; +} +``` + +This function should be embedded in the Java code: + +```java +/* read spreadsheet bytes */ +engine.put("bytes", Files.readAllBytes(Paths.get(args[0]))); + +/* convert signed byte array to JS Uint8Array or unsigned byte array */ +engine.eval( + "function b2a(b) {" + + "var out = typeof Uint8Array == 'function' ? new Uint8Array(b.length) : new Array(b.length);" + + "for(var i = 0; i < out.length; i++) out[i] = (b[i] + 256) & 0xFF;" + + "return out;" + + "}" + + "var u8a = b2a(bytes)" +); + +/* parse workbook */ +engine.eval("var wb = XLSX.read(u8a, {type: 'array'})"); +``` + +## Complete Example + +:::note + +This demo was last tested on 2023 March 27 using: + +- OpenJDK 19.0.1 + Nashorn 15.4 standalone +- OpenJDK 11.0.18 + Official Nashorn + +::: + + + + +Nashorn is available without additional dependencies + + + + +0) Download Nashorn and its dependencies: + +```bash +curl -LO "https://search.maven.org/remotecontent?filepath=org/openjdk/nashorn/nashorn-core/15.4/nashorn-core-15.4.jar" +curl -LO "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm/9.5/asm-9.5.jar" +curl -LO "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-tree/9.5/asm-tree-9.5.jar" +curl -LO "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-commons/9.5/asm-commons-9.5.jar" +curl -LO "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-analysis/9.5/asm-analysis-9.5.jar" +curl -LO "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-util/9.5/asm-util-9.5.jar" +``` + + + + +1) Download the standalone script, shim script, and the test file: + + + +```bash +curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js +curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js +curl -LO https://sheetjs.com/pres.xlsx +``` + +2) Download [`SheetJSNashorn.java`](pathname:///nashorn/SheetJSNashorn.java): + +```bash +curl -LO https://docs.sheetjs.com/nashorn/SheetJSNashorn.java +``` + +3) Build the sample class: + +```bash +javac SheetJSNashorn.java +``` + +This program tries to parse the file specified by the first argument + +4) Run the command directly: + + + + +```bash +java SheetJSNashorn pres.xlsx +``` + + + + +```bash +java -cp .:asm-9.5.jar:asm-tree-9.5.jar:asm-commons-9.5.jar:asm-analysis-9.5.jar:asm-util-9.5.jar:nashorn-core-15.4.jar SheetJSNashorn pres.xlsx +``` + + + + + +5) Assemble a Java Archive: + +```bash +jar -cf SheetJSNashorn.jar SheetJSNashorn.class xlsx.full.min.js shim.min.js +``` + +6) Verify the Java Archive. + +Create new directory and copy the archives and test file: + +```bash +mkdir -p sheethorn +cp *.jar pres.xlsx sheethorn +cd sheethorn +``` + +Invoke the command in the archive: + + + + +```bash +java -cp .:SheetJSNashorn.jar SheetJSNashorn pres.xlsx +``` + + + + +```bash +java -cp .:asm-9.5.jar:asm-tree-9.5.jar:asm-commons-9.5.jar:asm-analysis-9.5.jar:asm-util-9.5.jar:nashorn-core-15.4.jar:SheetJSNashorn.jar SheetJSNashorn pres.xlsx +``` + + + + diff --git a/docz/docs/03-demos/12-engines/index.md b/docz/docs/03-demos/12-engines/index.md index cc57493..b0b2e7f 100644 --- a/docz/docs/03-demos/12-engines/index.md +++ b/docz/docs/03-demos/12-engines/index.md @@ -240,6 +240,13 @@ build/bin/jerry xlsx.jerry.js; echo $? +### Nashorn + +Nashorn shipped with some versions of Java. It is now a standalone library. + +This demo has been moved [to a dedicated page](/docs/demos/engines/nashorn). + + ### QuickJS QuickJS is an embeddable JS engine written in C. It provides a separate set of @@ -255,15 +262,6 @@ Rhino is an ES3+ engine in Java. This demo has been moved [to a dedicated page](/docs/demos/engines/rhino). -## Legacy Engines - -:::warning - -These examples were written when the engines were maintained. New projects -should not use these engines. The demos are included for legacy deployments. - -::: - ### ChakraCore :::caution @@ -342,90 +340,3 @@ ready, it will read the bundled test data and print the contents as CSV. ``` - - -### Nashorn - -:::caution - -Nashorn shipped with Java 8. It was deprecated in Java 11 and was officially -removed in JDK 15. New Java applications should use [Rhino](#rhino). - -::: - - -Nashorn ships with Java. It includes a command-line tool `jjs` for running JS -scripts. It is somewhat limited but does offer access to the full Java runtime. - -The `load` function in `jjs` can load the minified source directly: - -```js -var global = (function(){ return this; }).call(null); -load('shim.min.js'); -load('xlsx.full.min.js'); -``` - -The Java `nio` API provides the `Files.readAllBytes` method to read a file into -a byte array. To use in `XLSX.read`, the demo copies the bytes into a plain JS -array and calls `XLSX.read` with type `"array"`. - -
Complete Example (click to show) - -0) Ensure `jjs` is available on system path - -1) Download the standalone script, the shim and the test file: - - - -2) Save the following script to `SheetJSNashorn.js`: - -```js title="SheetJSNashorn.js" -/* sheetjs (C) 2013-present SheetJS -- https://sheetjs.com */ - -/* load module */ -var global = (function(){ return this; }).call(null); -load('shim.min.js'); -load('xlsx.full.min.js'); - -/* helper to convert byte array to plain JS array */ -function b2a(b) { - var out = new Array(b.length); - for(var i = 0; i < out.length; i++) out[i] = (b[i] < 0 ? b[i] + 256 : b[i]); - return out; -} - -function process_file(path) { - java.lang.System.out.println(path); - - /* read file */ - var path = java.nio.file.Paths.get(path); - var bytes = java.nio.file.Files.readAllBytes(path); - var u8a = b2a(bytes); - - /* read data */ - var wb = XLSX.read(u8a); - - /* get first worksheet as an array of arrays */ - var ws = wb.Sheets[wb.SheetNames[0]]; - var js = XLSX.utils.sheet_to_json(ws, {header:1}); - - /* print out every line */ - js.forEach(function(l) { java.lang.System.out.println(JSON.stringify(l)); }); -} - -process_file('pres.numbers'); -``` - -3) Test the script: - -```bash -jjs SheetJSNashorn.js -``` - -It will print out the first worksheet contents. - -
diff --git a/docz/static/nashorn/SheetJSNashorn.java b/docz/static/nashorn/SheetJSNashorn.java new file mode 100644 index 0000000..d9a9340 --- /dev/null +++ b/docz/static/nashorn/SheetJSNashorn.java @@ -0,0 +1,37 @@ +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Scanner; + +public class SheetJSNashorn { + public static void main(String[] args) throws Exception { + /* initialize */ + ScriptEngine engine = (new ScriptEngineManager()).getEngineByName("javascript"); + + /* read script file */ + engine.eval("var global = (function(){ return this; }).call(null);"); + engine.eval(new Scanner(SheetJSNashorn.class.getResourceAsStream("/shim.min.js")).useDelimiter("\\Z").next()); + engine.eval(new Scanner(SheetJSNashorn.class.getResourceAsStream("/xlsx.full.min.js")).useDelimiter("\\Z").next()); + engine.eval("print('SheetJS Version ' + XLSX.version);"); + + /* read spreadsheet bytes */ + engine.put("bytes", Files.readAllBytes(Paths.get(args[0]))); + + /* convert signed byte array to JS Uint8Array or unsigned byte array */ + engine.eval("function b2a(b) {" + + "var out = typeof Uint8Array == 'function' ? new Uint8Array(b.length) : new Array(b.length);" + + "for(var i = 0; i < out.length; i++) out[i] = (b[i] + 256) & 0xFF;" + + "return out;" + + "}" + + "var u8a = b2a(bytes)"); + + /* parse workbook */ + engine.eval("var wb = XLSX.read(u8a, {type: 'array'})"); + + /* get first worksheet as CSV */ + engine.eval("var ws = wb.Sheets[wb.SheetNames[0]];"); + Object res = engine.eval("XLSX.utils.sheet_to_csv(ws)"); + System.out.println(res); + } +}