0
# Configuration & Context Management
1
2
Advanced configuration capabilities for GraalJS ScriptEngine including security settings, performance options, and polyglot context management. Provides multiple configuration approaches from simple binding-based options to full polyglot context builders.
3
4
## Capabilities
5
6
### Direct Engine Creation
7
8
Static factory methods for creating GraalJSScriptEngine instances with various levels of customization.
9
10
```java { .api }
11
/**
12
* Creates a new GraalJSScriptEngine with default configuration
13
* Default includes syntax extensions, load/print/arguments support enabled
14
* @return New GraalJSScriptEngine with standard settings
15
*/
16
static GraalJSScriptEngine create();
17
18
/**
19
* Creates a new GraalJSScriptEngine with custom polyglot engine and context configuration
20
* @param engine Polyglot engine to use (null for default)
21
* @param newContextConfig Base configuration for new contexts (null for default)
22
* @return New GraalJSScriptEngine with custom configuration
23
*/
24
static GraalJSScriptEngine create(Engine engine, Context.Builder newContextConfig);
25
```
26
27
**Usage Examples:**
28
29
```java
30
// Simple default creation
31
GraalJSScriptEngine defaultEngine = GraalJSScriptEngine.create();
32
defaultEngine.eval("console.log('Hello, World!');");
33
34
// Custom engine with specific options
35
Engine customEngine = Engine.newBuilder()
36
.allowExperimentalOptions(true)
37
.option("engine.MaxCompilationDelay", "5000")
38
.build();
39
40
Context.Builder contextConfig = Context.newBuilder("js")
41
.allowHostAccess(HostAccess.ALL)
42
.allowIO(IOAccess.ALL)
43
.option("js.ecmascript-version", "2022");
44
45
GraalJSScriptEngine customEngine = GraalJSScriptEngine.create(customEngine, contextConfig);
46
47
// Custom configuration without custom engine
48
GraalJSScriptEngine configuredEngine = GraalJSScriptEngine.create(null, contextConfig);
49
```
50
51
### Polyglot Context Access
52
53
Direct access to underlying GraalVM polyglot contexts for advanced operations and fine-grained control.
54
55
```java { .api }
56
/**
57
* Returns the polyglot context associated with the default ScriptContext
58
* @return GraalVM polyglot Context instance
59
*/
60
Context getPolyglotContext();
61
62
/**
63
* Returns the polyglot context associated with a specific ScriptContext
64
* If context not initialized, creates it using default context builder
65
* @param scriptContext The ScriptContext to get polyglot context for
66
* @return GraalVM polyglot Context instance for the ScriptContext
67
*/
68
Context getPolyglotContext(ScriptContext scriptContext);
69
70
/**
71
* Returns the polyglot engine associated with this script engine
72
* @return GraalVM polyglot Engine instance
73
*/
74
Engine getPolyglotEngine();
75
```
76
77
**Usage Examples:**
78
79
```java
80
GraalJSScriptEngine engine = GraalJSScriptEngine.create();
81
82
// Access default polyglot context
83
Context defaultContext = engine.getPolyglotContext();
84
Value jsBindings = defaultContext.getBindings("js");
85
jsBindings.putMember("javaObject", new Object());
86
87
// Work with multiple script contexts
88
SimpleScriptContext context1 = new SimpleScriptContext();
89
SimpleScriptContext context2 = new SimpleScriptContext();
90
91
Context polyContext1 = engine.getPolyglotContext(context1);
92
Context polyContext2 = engine.getPolyglotContext(context2);
93
94
// Each ScriptContext has its own polyglot context
95
assert polyContext1 != polyContext2;
96
assert polyContext1.getEngine() == polyContext2.getEngine();
97
98
// Direct polyglot operations
99
polyContext1.eval("js", "var ctx1Variable = 'context1'");
100
polyContext2.eval("js", "var ctx2Variable = 'context2'");
101
102
// Access polyglot engine
103
Engine polyEngine = engine.getPolyglotEngine();
104
System.out.println("Engine version: " + polyEngine.getVersion());
105
```
106
107
### Magic Binding Configuration
108
109
Configure GraalJS context options through special binding keys that are processed during context initialization.
110
111
```java { .api }
112
// Magic binding option prefix constant
113
static final String MAGIC_OPTION_PREFIX = "polyglot.js.";
114
115
// Magic binding option keys (set via Bindings.put() before context initialization)
116
"polyglot.js.allowHostAccess" // Boolean - Enable/disable host object access
117
"polyglot.js.allowNativeAccess" // Boolean - Enable/disable native library access
118
"polyglot.js.allowCreateThread" // Boolean - Enable/disable thread creation
119
"polyglot.js.allowIO" // Boolean - Enable/disable I/O operations
120
"polyglot.js.allowHostClassLookup" // Boolean or Predicate<String> - Control class lookup
121
"polyglot.js.allowHostClassLoading" // Boolean - Enable/disable class loading
122
"polyglot.js.allowAllAccess" // Boolean - Enable/disable all access permissions
123
"polyglot.js.nashorn-compat" // Boolean - Enable/disable Nashorn compatibility mode
124
"polyglot.js.ecmascript-version" // String - Set ECMAScript version
125
"polyglot.js.intl-402" // Boolean - Enable/disable Intl API support
126
```
127
128
**Usage Examples:**
129
130
```java
131
ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
132
Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
133
134
// Configure security options BEFORE first evaluation
135
bindings.put("polyglot.js.allowHostAccess", true);
136
bindings.put("polyglot.js.allowHostClassLookup", (Predicate<String>) s -> s.startsWith("java."));
137
bindings.put("polyglot.js.allowIO", false); // Disable I/O for security
138
139
// Configure language options
140
bindings.put("polyglot.js.ecmascript-version", "2022");
141
bindings.put("polyglot.js.nashorn-compat", false);
142
143
// Set Java objects accessible to JavaScript
144
bindings.put("javaList", Arrays.asList(1, 2, 3));
145
bindings.put("javaMap", Map.of("key", "value"));
146
147
// Now evaluate - context will be initialized with configured options
148
engine.eval("console.log(javaList.length);"); // Works due to allowHostAccess
149
engine.eval("console.log(Java.type('java.lang.String'));"); // Works due to allowHostClassLookup
150
151
// Attempting to set magic options after context initialization fails
152
try {
153
engine.eval("var dummy = true;"); // Forces context initialization
154
bindings.put("polyglot.js.allowIO", true); // This will throw IllegalStateException
155
} catch (IllegalStateException e) {
156
System.out.println("Cannot set options after context initialization");
157
}
158
```
159
160
### System Property Configuration
161
162
Configure GraalJS options globally through JVM system properties.
163
164
**System Property Format:**
165
```bash
166
# Engine options (affect all ScriptEngine instances)
167
-Dpolyglot.js.ecmascript-version=2022
168
-Dpolyglot.js.intl-402=true
169
170
# Global compatibility mode
171
-Dpolyglot.js.nashorn-compat=true
172
173
# Insecure access mode (development only)
174
-Dgraaljs.insecure-scriptengine-access=true
175
```
176
177
**Usage Examples:**
178
179
```java
180
// Set system properties programmatically (before creating engines)
181
System.setProperty("polyglot.js.ecmascript-version", "2022");
182
System.setProperty("polyglot.js.intl-402", "true");
183
184
// Create engines - they inherit system property settings
185
ScriptEngine engine1 = new ScriptEngineManager().getEngineByName("js");
186
ScriptEngine engine2 = new ScriptEngineManager().getEngineByName("js");
187
188
// Both engines use ES2022 with Intl support
189
engine1.eval("console.log(Object.hasOwn({}, 'prop'));"); // ES2022 feature
190
engine2.eval("console.log(new Intl.DateTimeFormat('en-US'));"); // Intl API
191
192
// Command line usage:
193
// java -Dpolyglot.js.ecmascript-version=2022 -Dpolyglot.js.nashorn-compat=true MyApp
194
```
195
196
### Custom Context Builder Configuration
197
198
Full control over polyglot context configuration through direct Context.Builder usage.
199
200
```java { .api }
201
/**
202
* Example Context.Builder configuration options
203
*/
204
Context.Builder contextBuilder = Context.newBuilder("js")
205
// Security settings
206
.allowHostAccess(HostAccess.ALL) // Or HostAccess.NONE, custom HostAccess
207
.allowHostClassLookup(s -> true) // Or specific predicate
208
.allowHostClassLoading(true)
209
.allowNativeAccess(true)
210
.allowCreateThread(true)
211
.allowIO(IOAccess.ALL) // Or IOAccess.NONE
212
.allowAllAccess(true) // Enables all permissions
213
214
// Language options
215
.option("js.ecmascript-version", "2022")
216
.option("js.intl-402", "true")
217
.option("js.nashorn-compat", "true")
218
.option("js.syntax-extensions", "true")
219
220
// I/O configuration
221
.in(System.in)
222
.out(System.out)
223
.err(System.err)
224
225
// Engine configuration
226
.allowExperimentalOptions(true);
227
```
228
229
**Usage Examples:**
230
231
```java
232
// Secure configuration for untrusted code
233
Context.Builder secureConfig = Context.newBuilder("js")
234
.allowHostAccess(HostAccess.NONE)
235
.allowHostClassLookup(s -> false)
236
.allowHostClassLoading(false)
237
.allowNativeAccess(false)
238
.allowCreateThread(false)
239
.allowIO(IOAccess.NONE)
240
.option("js.ecmascript-version", "2022");
241
242
GraalJSScriptEngine secureEngine = GraalJSScriptEngine.create(null, secureConfig);
243
244
// Permissive configuration for trusted code
245
Context.Builder permissiveConfig = Context.newBuilder("js")
246
.allowAllAccess(true)
247
.allowHostClassLookup(s -> true)
248
.option("js.nashorn-compat", "true")
249
.option("js.ecmascript-version", "2022");
250
251
GraalJSScriptEngine permissiveEngine = GraalJSScriptEngine.create(null, permissiveConfig);
252
253
// Development configuration with custom I/O
254
StringWriter output = new StringWriter();
255
StringWriter errors = new StringWriter();
256
257
Context.Builder devConfig = Context.newBuilder("js")
258
.allowAllAccess(true)
259
.out(new WriterOutputStream(output, StandardCharsets.UTF_8))
260
.err(new WriterOutputStream(errors, StandardCharsets.UTF_8))
261
.option("js.syntax-extensions", "true");
262
263
GraalJSScriptEngine devEngine = GraalJSScriptEngine.create(null, devConfig);
264
devEngine.eval("console.log('Hello'); console.error('Warning');");
265
System.out.println("Output: " + output.toString());
266
System.out.println("Errors: " + errors.toString());
267
```
268
269
### Nashorn Compatibility Mode
270
271
Special compatibility mode for applications migrating from Oracle Nashorn ScriptEngine.
272
273
```java { .api }
274
// Enable via system property
275
System.setProperty("polyglot.js.nashorn-compat", "true");
276
277
// Enable via magic binding
278
bindings.put("polyglot.js.nashorn-compat", true);
279
280
// Enable via context builder
281
Context.Builder nashornConfig = Context.newBuilder("js")
282
.option("js.nashorn-compat", "true");
283
```
284
285
**Nashorn Compatibility Features:**
286
- Automatic host access permissions
287
- Nashorn-style type conversions
288
- Extended compatibility for legacy code
289
- System.exit() support
290
291
**Usage Examples:**
292
293
```java
294
// Global Nashorn compatibility
295
System.setProperty("polyglot.js.nashorn-compat", "true");
296
ScriptEngine nashornCompatEngine = new ScriptEngineManager().getEngineByName("js");
297
298
// Nashorn-style operations work automatically
299
nashornCompatEngine.put("javaObject", new Object());
300
nashornCompatEngine.eval("print(javaObject.getClass().getName());");
301
302
// Per-engine Nashorn compatibility
303
ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
304
Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
305
bindings.put("polyglot.js.nashorn-compat", true);
306
bindings.put("polyglot.js.allowAllAccess", true);
307
308
engine.eval("var ArrayList = Java.type('java.util.ArrayList');");
309
engine.eval("var list = new ArrayList(); list.add('item');");
310
```
311
312
### Resource Management
313
314
Proper lifecycle management of engines, contexts, and associated resources.
315
316
```java { .api }
317
/**
318
* Closes the current context and makes it unusable
319
* Operations performed after closing will throw IllegalStateException
320
*/
321
void close();
322
323
/**
324
* Check if context is closed
325
*/
326
boolean isClosed(); // Available on polyglot Context
327
```
328
329
**Usage Examples:**
330
331
```java
332
// Automatic resource management
333
try (GraalJSScriptEngine engine = GraalJSScriptEngine.create()) {
334
engine.eval("console.log('Working...');");
335
// Engine automatically closed when leaving try block
336
}
337
338
// Manual resource management
339
GraalJSScriptEngine engine = GraalJSScriptEngine.create();
340
try {
341
engine.eval("var result = computeExpensiveOperation();");
342
Object result = engine.get("result");
343
return result;
344
} finally {
345
engine.close(); // Ensure cleanup
346
}
347
348
// Managing polyglot contexts directly
349
Context polyglotContext = engine.getPolyglotContext();
350
try {
351
polyglotContext.eval("js", "performWork()");
352
} finally {
353
if (!polyglotContext.isClosed()) {
354
polyglotContext.close();
355
}
356
}
357
358
// Resource sharing with custom engine
359
Engine sharedEngine = Engine.newBuilder().build();
360
try {
361
GraalJSScriptEngine engine1 = GraalJSScriptEngine.create(sharedEngine, null);
362
GraalJSScriptEngine engine2 = GraalJSScriptEngine.create(sharedEngine, null);
363
364
// Use both engines - they share the polyglot engine
365
engine1.eval("var shared = 'data';");
366
engine2.eval("var other = 'data';");
367
368
// Close individual engines
369
engine1.close();
370
engine2.close();
371
} finally {
372
// Close shared engine when all ScriptEngines are done
373
sharedEngine.close();
374
}
375
```
376
377
## Configuration Best Practices
378
379
### Security Configuration
380
- Always use minimal required permissions
381
- Disable host access for untrusted code
382
- Use allowHostClassLookup predicates to restrict class access
383
- Disable I/O and native access unless required
384
385
### Performance Configuration
386
- Reuse ScriptEngine instances when possible
387
- Use CompiledScript for repeated execution
388
- Share polyglot Engine across multiple ScriptEngines
389
- Enable experimental options for performance tuning
390
391
### Migration from Nashorn
392
- Enable nashorn-compat mode initially
393
- Gradually migrate to modern GraalJS features
394
- Test thoroughly as compatibility is not 100%
395
- Consider direct polyglot API for new development