java-js: A Lightweight JavaScript Subset for the JVM

Have you ever wished for the flexibility of JavaScript syntax with the performance and reliability of the JVM? That’s exactly what java-js delivers. I’m excited to share this project that implements a carefully curated subset of JavaScript features designed specifically for Java environments.
What is java-js?
java-js is a minimalist JavaScript interpreter that runs natively on the JVM. It provides syntax compatibility with a selected subset of JavaScript while using native Java objects under the hood. This means code written for java-js can be executed in standard JavaScript engines, but not necessarily vice versa.
One of the key differences is that java-js eliminates many of JavaScript’s quirky behaviors (the “WTF moments” that often confuse developers) in favor of more predictable operations.
The Power of AI Collaboration
An interesting aspect of this project is that it was developed in collaboration with Claude 3.7, Anthropic’s language model. Claude contributed significantly to the implementation of core components:
Component | Claude 3.7 | My Contribution |
---|---|---|
Lexer | 90% | 10% |
Parser | 80% | 20% |
AstNodes | 70% | 30% |
Types & Ops | 70% | 30% |
SDK Functions | 80% | 20% |
Tests | 100% | 0% |
Documentation | 90% | 10% |
This collaboration demonstrates how AI can accelerate development by handling implementation details while I focused on architectural decisions and integration.
Key Features
Supported Types
- All the basics:
null
,undefined
,boolean
, andnumber
(asint
,long
, anddouble
) - Collections as
array
(JavaList
) andobject
(JavaMap
) - First-class functions using custom
JsFunction
or nativeBiFunction
, Object>> - Error handling
JavaScript Syntax Support
- Variable declarations with
var
,let
, andconst
- Standard operators including assignments and arithmetic
- Control flow with conditionals and loops
- Modern JavaScript features like:
- Arrow functions
- Template literals
- Optional chaining
- Null coalescing operator
- Partial Array and Object destructing
Compile Once, Run Many
One of the project’s strengths is its thread-safe design. Once a script is compiled to an AST, it can be executed multiple times across different threads without risk of shared state corruption:
JsLexer lexer = new JsLexer(script);
JsParser parser = new JsParser(lexer.tokenize());
ASTNode programNode = parser.parse();
// Run in parallel or sequentially as needed
for(int i=0; i<10; i++){
Scope rootScope = JsSdk.createRootScope();
programNode.exec(rootScope);
}
Use Cases
java-js is perfect for:
- Embedding a scripting engine in Java applications
- Creating domain-specific languages with JavaScript-like syntax
- Configuration scripts that need conditional logic
- Providing a safe execution environment for user-defined logic
An Example
Here’s how simple it is to use java-js:
import eu.aston.javajs.*;
import eu.aston.javajs.AstNodes.ASTNode;
String script = """
var a = 5;
let b = 10;
const sum = (x, y) => x + y;
var result = sum(a, b);
""";
Scope rootScope = JsSdk.createRootScope();
JsLexer lexer = new JsLexer(script);
JsParser parser = new JsParser(lexer.tokenize());
ASTNode programNode = parser.parse();
programNode.exec(rootScope);
Integer result = rootScope.getVar("result").value();
Try It Out
java-js is available as a Maven dependency:
eu.aston
java-js
1.0.0
The complete source code is available on GitHub: https://github.com/pm3/java-js
Not Supported:
-
new
operator async/await
-
class
,instanceof
import/export
fetch
-
regex
– no regex object, onlyString
parameter inString.match
orString.matchAll
- some JavaScript WTF behaviors (like
[] == 0
, etc.)
Conclusion
java-js brings the simplicity and expressiveness of JavaScript syntax to the JVM while avoiding many of JavaScript’s pitfalls. Whether you need a lightweight scripting solution for your Java application or just want to explore language implementation, I invite you to check out the project.
I’d love to hear your thoughts and feedback! What features would you like to see added in future versions?