6.9 KiB
title | pagination_prev | pagination_next |
---|---|---|
JavaScript Engines | demos/bigdata/index | solutions/input |
import current from '/version.js'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';
Browser vendors and other organizations have built "JavaScript engines". They are independent software libraries that are capable of running JS scripts.
The most popular JavaScript engine is V8. Designed for embedding in software, it powers Chrome, NodeJS, UXP, Deno and many other platforms.
There are many other JS engines with different design goals. Some are designed for low-power or low-memory environments. Others aim for interoperability with specific programming languages or environments. Typically they support ES3 and are capable of running SheetJS code.
This demo showcases a number of JS engines and language bindings.
General Caveats
Common browser and NodeJS APIs are often missing from light-weight JS engines.
Global
Some engines do not provide globalThis
or global
or window
. A global
variable can be exposed in one line that should be run in the JS engine:
var global = (function(){ return this; }).call(null);
Console
Some engines do not provide a console
object. console.log
can be shimmed
using the engine functionality. For example, hermes
provides print()
:
var console = { log: function(x) { print(x); } };
Binary Data
Some engines do not provide easy ways to exchange binary data. For example, it is common to pass null-terminated arrays, which would truncate XLSX, XLS, and other exports. APIs that accept pointers without length should be avoided.
Base64 strings are safe for passing between JS and native code, but they should
only be used when there is no safe way to pass ArrayBuffer
or Uint8Array
.
Byte Conventions
Java has no native concept of unsigned bytes. Values in a byte[]
are clamped
to the range -128 .. 127
. They need to be fixed within the JS engine.
Some engines support typed arrays. The Uint8Array
constructor will fix values:
var signed_data = [-48, -49, 17, -32, /* ... */]; // 0xD0 0xCF 0x11 0xE0 ...
var fixed_data = new Uint8Array(signed_data);
When Uint8Array
is not supported, values can be fixed with bitwise operations:
var signed_data = [-48, -49, 17, -32, /* ... */]; // 0xD0 0xCF 0x11 0xE0 ...
var fixed_data = new Array(signed_data.length);
for(var i = 0; i < signed_data.length; ++i) fixed_data[i] = signed_data[i] & 0xFF;
Engines
This list is sorted in alphabetical order.
Boa
Boa is an embeddable JS engine written in Rust.
This demo has been moved to a dedicated page.
ChakraCore
ChakraCore is an embeddable JS engine written in C++.
This demo has been moved to a dedicated page.
Duktape
Duktape is an embeddable JS engine written in C. It has been ported to a number of exotic architectures and operating systems.
This demo has been moved to a dedicated page. The demo includes examples in C and Perl.
Goja
Goja is a pure Go implementation of ECMAScript 5.
This demo has been moved to a dedicated page.
Hermes
Hermes is an embeddable JS engine written in C++.
This demo has been moved to a dedicated page.
JavaScriptCore
iOS and MacOS ship with the JavaScriptCore framework for running JS code from Swift and Objective-C.
This demo has been moved to a dedicated page.
JerryScript
JerryScript is a lightweight JavaScript engine designed for use in low-memory environments like microcontrollers. As part of the build suite, the project generates a C library and a standalone CLI tool.
The simplest way to interact with the engine is to pass Base64 strings.
:::note
While applications should link against the official libraries, the standalone tool is useful for verifying functionality.
:::
:::caution
This demo requires a much larger heap size than is normally used in JerryScript deployments! In local testing, the following sizes were needed:
- 8192 (8M) for https://sheetjs.com/pres.xlsx
- 65536 (64M) for https://sheetjs.com/pres.numbers
This works on a Raspberry Pi.
:::
Complete Example (click to show)
Due to limitations of the standalone binary, this demo will encode a test file as a Base64 string and directly add it to an amalgamated script.
- Build the library and command line tool with required options:
git clone --depth=1 https://github.com/jerryscript-project/jerryscript.git
cd jerryscript
python tools/build.py --error-messages=ON --logging=ON --mem-heap=8192 --cpointer-32bit=ON
- Download the standalone script, shim, and test file:
- xlsx.full.min.js
- shim.min.js
- pres.xlsx
- Bundle the test file and create
payload.js
:
node -e "fs.writeFileSync('payload.js', 'var payload = \"' + fs.readFileSync('pres.xlsx').toString('base64') + '\";')"
- Create support scripts:
global.js
creates aglobal
variable and defines a fakeconsole
:
var global = (function(){ return this; }).call(null);
var console = { log: function(x) { print(x); } };
jerry.js
will callXLSX.read
andXLSX.utils.sheet_to_csv
:
/* sheetjs (C) 2013-present SheetJS -- https://sheetjs.com */
var wb = XLSX.read(payload, {type:'base64'});
console.log(XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]));
- Create the amalgamation
xlsx.jerry.js
:
cat global.js xlsx.full.min.js payload.js jerry.js > xlsx.jerry.js
The final script defines global
before loading the standalone library. Once
ready, it will read the bundled test data and print the contents as CSV.
- Run the script using the
jerry
standalone binary:
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.
QuickJS
QuickJS is an embeddable JS engine written in C. It provides a separate set of functions for interacting with the filesystem and the global object. It can run the standalone browser scripts.
This demo has been moved to a dedicated page.
Rhino
Rhino is an ES3+ engine in Java.
This demo has been moved to a dedicated page.
V8
V8 is an embeddable JS engine written in C++. It powers Chromium and Chrome, NodeJS and Deno, Adobe UXP and other platforms.
This demo has been moved to a dedicated page. The demo includes examples in C++ and Rust.