0
# Value Types and Host-Guest Interoperability
1
2
The Value class is the central abstraction for language-agnostic operations on polyglot values. It provides seamless interoperability between host (Java) and guest languages, enabling type conversion, container operations, and function execution across language boundaries.
3
4
## Value Type System
5
6
The Value class provides comprehensive type checking and conversion capabilities for all supported polyglot value types.
7
8
### Basic Type Checking
9
10
```java { .api }
11
public final class Value extends AbstractValue {
12
// Null and basic type checks
13
public boolean isNull();
14
public boolean isNumber();
15
public boolean isBoolean();
16
public boolean isString();
17
18
// Object type checks
19
public boolean isHostObject();
20
public boolean isProxyObject();
21
public boolean isNativePointer();
22
23
// Temporal type checks
24
public boolean isDate();
25
public boolean isTime();
26
public boolean isTimeZone();
27
public boolean isDuration();
28
public boolean isInstant();
29
30
// Exception checking
31
public boolean isException();
32
}
33
```
34
35
**Type Checking Example:**
36
37
```java
38
Context context = Context.create("js");
39
40
Value stringValue = context.eval("js", "'Hello World'");
41
Value numberValue = context.eval("js", "42.5");
42
Value arrayValue = context.eval("js", "[1, 2, 3]");
43
Value objectValue = context.eval("js", "({name: 'Alice', age: 30})");
44
45
System.out.println(stringValue.isString()); // true
46
System.out.println(numberValue.isNumber()); // true
47
System.out.println(arrayValue.hasArrayElements()); // true
48
System.out.println(objectValue.hasMembers()); // true
49
```
50
51
### Basic Type Conversion
52
53
```java { .api }
54
// Primitive type conversion
55
public boolean asBoolean();
56
public String asString();
57
public int asInt();
58
public long asLong();
59
public float asFloat();
60
public double asDouble();
61
public byte asByte();
62
public short asShort();
63
64
// Temporal type conversion
65
public LocalDate asDate();
66
public LocalTime asTime();
67
public ZoneId asTimeZone();
68
public Duration asDuration();
69
public Instant asInstant();
70
71
// Object type conversion
72
public long asNativePointer();
73
public <T> T asHostObject();
74
public <T extends Proxy> T asProxyObject();
75
```
76
77
**Type Conversion Examples:**
78
79
```java
80
Context context = Context.create("js");
81
82
// JavaScript number to Java types
83
Value jsNumber = context.eval("js", "Math.PI");
84
double pi = jsNumber.asDouble(); // 3.141592653589793
85
int piInt = jsNumber.asInt(); // 3 (truncated)
86
String piStr = jsNumber.asString(); // "3.141592653589793"
87
88
// JavaScript string to Java types
89
Value jsString = context.eval("js", "'42'");
90
int fromString = jsString.asInt(); // 42 (parsed)
91
String original = jsString.asString(); // "42"
92
93
// JavaScript boolean
94
Value jsBool = context.eval("js", "true");
95
boolean bool = jsBool.asBoolean(); // true
96
String boolStr = jsBool.asString(); // "true"
97
```
98
99
### Generic Type Conversion
100
101
```java { .api }
102
// Type-safe conversion with Class
103
public <T> T as(Class<T> targetType);
104
105
// Type-safe conversion with TypeLiteral
106
public <T> T as(TypeLiteral<T> targetType);
107
```
108
109
**Generic Conversion Examples:**
110
111
```java
112
Context context = Context.create("js");
113
114
// JavaScript array to Java List
115
Value jsArray = context.eval("js", "[1, 2, 3, 4, 5]");
116
List<Integer> javaList = jsArray.as(List.class);
117
System.out.println(javaList); // [1, 2, 3, 4, 5]
118
119
// JavaScript object to Java Map
120
Value jsObject = context.eval("js", "({name: 'Alice', age: 30})");
121
Map<String, Object> javaMap = jsObject.as(Map.class);
122
System.out.println(javaMap.get("name")); // "Alice"
123
124
// Custom type conversion with TypeLiteral
125
Value jsListOfMaps = context.eval("js", "[{x: 1}, {x: 2}, {x: 3}]");
126
TypeLiteral<List<Map<String, Integer>>> listType = new TypeLiteral<List<Map<String, Integer>>>() {};
127
List<Map<String, Integer>> typedList = jsListOfMaps.as(listType);
128
```
129
130
## Container Operations
131
132
The Value class provides unified access to container-like objects including arrays, objects with members, and hash maps.
133
134
### Array Operations
135
136
```java { .api }
137
// Array type checking and access
138
public boolean hasArrayElements();
139
public long getArraySize();
140
public Value getArrayElement(long index);
141
public void setArrayElement(long index, Object value);
142
public boolean removeArrayElement(long index);
143
```
144
145
**Array Manipulation Examples:**
146
147
```java
148
Context context = Context.create("js");
149
150
// Create and access JavaScript array
151
Value jsArray = context.eval("js", "['hello', 'world', 42, true]");
152
153
System.out.println(jsArray.hasArrayElements()); // true
154
System.out.println(jsArray.getArraySize()); // 4
155
156
// Access elements
157
System.out.println(jsArray.getArrayElement(0).asString()); // "hello"
158
System.out.println(jsArray.getArrayElement(2).asInt()); // 42
159
160
// Modify array
161
jsArray.setArrayElement(1, "polyglot");
162
jsArray.setArrayElement(4, "new element"); // Extends array
163
164
// Remove elements
165
jsArray.removeArrayElement(3); // Remove boolean true
166
System.out.println(jsArray.getArraySize()); // 4
167
```
168
169
### Member Operations
170
171
```java { .api }
172
// Object member operations
173
public boolean hasMembers();
174
public Set<String> getMemberKeys();
175
public boolean hasMember(String identifier);
176
public Value getMember(String identifier);
177
public void putMember(String identifier, Object value);
178
public boolean removeMember(String identifier);
179
```
180
181
**Member Access Examples:**
182
183
```java
184
Context context = Context.create("js");
185
186
// Create JavaScript object
187
Value jsObject = context.eval("js", """
188
({
189
name: 'Alice',
190
age: 30,
191
greet: function() { return 'Hello, ' + this.name; },
192
address: {
193
city: 'San Francisco',
194
country: 'USA'
195
}
196
})
197
""");
198
199
System.out.println(jsObject.hasMembers()); // true
200
201
// Get all member keys
202
Set<String> keys = jsObject.getMemberKeys();
203
System.out.println(keys); // [name, age, greet, address]
204
205
// Access members
206
System.out.println(jsObject.getMember("name").asString()); // "Alice"
207
System.out.println(jsObject.getMember("age").asInt()); // 30
208
209
// Access nested members
210
Value address = jsObject.getMember("address");
211
System.out.println(address.getMember("city").asString()); // "San Francisco"
212
213
// Modify members
214
jsObject.putMember("age", 31);
215
jsObject.putMember("email", "alice@example.com");
216
217
// Remove members
218
jsObject.removeMember("address");
219
System.out.println(jsObject.hasMember("address")); // false
220
```
221
222
### Hash/Map Operations
223
224
```java { .api }
225
// Hash map operations (for languages that support map-like objects)
226
public boolean hasHashEntries();
227
public long getHashSize();
228
public boolean hasHashEntry(Object key);
229
public Value getHashValue(Object key);
230
public Value getHashValueOrDefault(Object key, Object defaultValue);
231
public void putHashEntry(Object key, Object value);
232
public boolean removeHashEntry(Object key);
233
public Value getHashEntriesIterator();
234
public Value getHashKeysIterator();
235
public Value getHashValuesIterator();
236
```
237
238
**Hash Operations Examples:**
239
240
```java
241
Context context = Context.create("js");
242
243
// Create a Map-like structure
244
Value jsMap = context.eval("js", "new Map([['key1', 'value1'], ['key2', 42]])");
245
246
if (jsMap.hasHashEntries()) {
247
System.out.println(jsMap.getHashSize()); // 2
248
249
// Access values
250
System.out.println(jsMap.getHashValue("key1").asString()); // "value1"
251
System.out.println(jsMap.getHashValue("key2").asInt()); // 42
252
253
// Add/modify entries
254
jsMap.putHashEntry("key3", "new value");
255
jsMap.putHashEntry("key1", "updated value");
256
257
// Iterate over entries
258
Value entriesIterator = jsMap.getHashEntriesIterator();
259
while (entriesIterator.hasIteratorNextElement()) {
260
Value entry = entriesIterator.getIteratorNextElement();
261
Value key = entry.getArrayElement(0);
262
Value value = entry.getArrayElement(1);
263
System.out.printf("%s -> %s%n", key.asString(), value.toString());
264
}
265
}
266
```
267
268
### Iterator Operations
269
270
```java { .api }
271
// Iterator support
272
public boolean hasIterator();
273
public Value getIterator();
274
public boolean isIterator();
275
public boolean hasIteratorNextElement();
276
public Value getIteratorNextElement();
277
```
278
279
**Iterator Examples:**
280
281
```java
282
Context context = Context.create("js");
283
284
// JavaScript iterable
285
Value jsIterable = context.eval("js", "[10, 20, 30, 40, 50]");
286
287
if (jsIterable.hasIterator()) {
288
Value iterator = jsIterable.getIterator();
289
290
while (iterator.hasIteratorNextElement()) {
291
Value element = iterator.getIteratorNextElement();
292
System.out.println(element.asInt());
293
}
294
}
295
296
// Custom iterator from JavaScript generator
297
Value jsGenerator = context.eval("js", """
298
(function* fibonacci() {
299
let a = 0, b = 1;
300
while (a < 100) {
301
yield a;
302
[a, b] = [b, a + b];
303
}
304
})()
305
""");
306
307
while (jsGenerator.hasIteratorNextElement()) {
308
Value fib = jsGenerator.getIteratorNextElement();
309
System.out.println(fib.asInt()); // 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89
310
}
311
```
312
313
## Function Execution
314
315
The Value class supports executing functions and constructors from guest languages with type-safe parameter passing.
316
317
### Function Execution
318
319
```java { .api }
320
// Function execution
321
public boolean canExecute();
322
public Value execute(Object... arguments);
323
public void executeVoid(Object... arguments);
324
325
// Constructor invocation
326
public boolean canInstantiate();
327
public Value newInstance(Object... arguments);
328
329
// Member method invocation
330
public boolean canInvokeMember(String identifier);
331
public Value invokeMember(String identifier, Object... arguments);
332
```
333
334
**Function Execution Examples:**
335
336
```java
337
Context context = Context.create("js");
338
339
// Define JavaScript function
340
Value jsFunction = context.eval("js", """
341
function calculate(operation, a, b) {
342
switch(operation) {
343
case 'add': return a + b;
344
case 'multiply': return a * b;
345
case 'power': return Math.pow(a, b);
346
default: return null;
347
}
348
}
349
calculate;
350
""");
351
352
if (jsFunction.canExecute()) {
353
Value result1 = jsFunction.execute("add", 5, 3);
354
Value result2 = jsFunction.execute("multiply", 4, 7);
355
Value result3 = jsFunction.execute("power", 2, 8);
356
357
System.out.println(result1.asInt()); // 8
358
System.out.println(result2.asInt()); // 28
359
System.out.println(result3.asInt()); // 256
360
}
361
362
// Constructor invocation
363
Value jsClass = context.eval("js", """
364
class Person {
365
constructor(name, age) {
366
this.name = name;
367
this.age = age;
368
}
369
370
greet() {
371
return `Hello, I'm ${this.name} and I'm ${this.age} years old.`;
372
}
373
}
374
Person;
375
""");
376
377
if (jsClass.canInstantiate()) {
378
Value person = jsClass.newInstance("Alice", 30);
379
Value greeting = person.invokeMember("greet");
380
System.out.println(greeting.asString()); // "Hello, I'm Alice and I'm 30 years old."
381
}
382
```
383
384
### Method Invocation
385
386
```java
387
Context context = Context.create("js");
388
389
// JavaScript object with methods
390
Value jsObject = context.eval("js", """
391
({
392
data: [1, 2, 3, 4, 5],
393
394
sum: function() {
395
return this.data.reduce((a, b) => a + b, 0);
396
},
397
398
filter: function(predicate) {
399
return this.data.filter(predicate);
400
},
401
402
map: function(transform) {
403
return this.data.map(transform);
404
}
405
})
406
""");
407
408
// Invoke methods
409
Value sum = jsObject.invokeMember("sum");
410
System.out.println(sum.asInt()); // 15
411
412
// Pass function as argument
413
Value squares = jsObject.invokeMember("map", context.eval("js", "x => x * x"));
414
System.out.println(squares.as(List.class)); // [1, 4, 9, 16, 25]
415
416
// Chain method calls
417
Value evenNumbers = jsObject.invokeMember("filter", context.eval("js", "x => x % 2 === 0"));
418
System.out.println(evenNumbers.as(List.class)); // [2, 4]
419
```
420
421
## Buffer Operations
422
423
For languages that support binary data, the Value class provides low-level buffer operations.
424
425
### Buffer Access
426
427
```java { .api }
428
// Buffer operations
429
public boolean hasBufferElements();
430
public boolean isBufferWritable();
431
public long getBufferSize();
432
433
// Byte operations
434
public byte readBufferByte(long byteOffset);
435
public void writeBufferByte(long byteOffset, byte value);
436
437
// Multi-byte operations with endianness
438
public short readBufferShort(ByteOrder order, long byteOffset);
439
public void writeBufferShort(ByteOrder order, long byteOffset, short value);
440
public int readBufferInt(ByteOrder order, long byteOffset);
441
public void writeBufferInt(ByteOrder order, long byteOffset, int value);
442
public long readBufferLong(ByteOrder order, long byteOffset);
443
public void writeBufferLong(ByteOrder order, long byteOffset, long value);
444
public float readBufferFloat(ByteOrder order, long byteOffset);
445
public void writeBufferFloat(ByteOrder order, long byteOffset, float value);
446
public double readBufferDouble(ByteOrder order, long byteOffset);
447
public void writeBufferDouble(ByteOrder order, long byteOffset, double value);
448
```
449
450
**Buffer Operations Example:**
451
452
```java
453
Context context = Context.create("js");
454
455
// Create JavaScript ArrayBuffer
456
Value jsBuffer = context.eval("js", "new ArrayBuffer(32)");
457
458
if (jsBuffer.hasBufferElements()) {
459
System.out.println("Buffer size: " + jsBuffer.getBufferSize()); // 32
460
System.out.println("Writable: " + jsBuffer.isBufferWritable()); // true
461
462
// Write various data types
463
jsBuffer.writeBufferInt(ByteOrder.BIG_ENDIAN, 0, 0x12345678);
464
jsBuffer.writeBufferFloat(ByteOrder.LITTLE_ENDIAN, 4, 3.14159f);
465
jsBuffer.writeBufferDouble(ByteOrder.BIG_ENDIAN, 8, Math.E);
466
467
// Read back the data
468
int intValue = jsBuffer.readBufferInt(ByteOrder.BIG_ENDIAN, 0);
469
float floatValue = jsBuffer.readBufferFloat(ByteOrder.LITTLE_ENDIAN, 4);
470
double doubleValue = jsBuffer.readBufferDouble(ByteOrder.BIG_ENDIAN, 8);
471
472
System.out.printf("Int: 0x%08X%n", intValue); // 0x12345678
473
System.out.printf("Float: %f%n", floatValue); // 3.141590
474
System.out.printf("Double: %f%n", doubleValue); // 2.718282
475
}
476
```
477
478
## Meta-Object Operations
479
480
The Value class provides access to meta-information about objects and their types.
481
482
### Meta-Object Protocol
483
484
```java { .api }
485
// Meta-object operations
486
public Value getMetaObject();
487
public boolean isMetaObject();
488
public String getMetaQualifiedName();
489
public String getMetaSimpleName();
490
public boolean isMetaInstance(Object instance);
491
public boolean hasMetaParents();
492
public Value getMetaParents();
493
```
494
495
**Meta-Object Examples:**
496
497
```java
498
Context context = Context.create("js");
499
500
// Create JavaScript object and get its meta-object
501
Value jsObject = context.eval("js", "new Date()");
502
Value metaObject = jsObject.getMetaObject();
503
504
if (metaObject.isMetaObject()) {
505
System.out.println("Type name: " + metaObject.getMetaSimpleName()); // "Date"
506
System.out.println("Qualified name: " + metaObject.getMetaQualifiedName()); // "Date"
507
508
// Check if another object is instance of this type
509
Value anotherDate = context.eval("js", "new Date(2023, 0, 1)");
510
boolean isInstance = metaObject.isMetaInstance(anotherDate);
511
System.out.println("Is instance: " + isInstance); // true
512
513
// Check parents/prototypes
514
if (metaObject.hasMetaParents()) {
515
Value parents = metaObject.getMetaParents();
516
System.out.println("Has parent types: " + parents.getArraySize());
517
}
518
}
519
```
520
521
## Host-Guest Integration
522
523
### Converting Java Objects to Values
524
525
```java
526
Context context = Context.newBuilder("js")
527
.allowHostAccess(HostAccess.EXPLICIT)
528
.build();
529
530
// Java class with exported members
531
public class Calculator {
532
@HostAccess.Export
533
public double add(double a, double b) {
534
return a + b;
535
}
536
537
@HostAccess.Export
538
public double multiply(double a, double b) {
539
return a * b;
540
}
541
}
542
543
// Convert to Value and use in JavaScript
544
Value calculatorValue = context.asValue(new Calculator());
545
Value jsBindings = context.getBindings("js");
546
jsBindings.putMember("calc", calculatorValue);
547
548
Value result = context.eval("js", "calc.add(calc.multiply(3, 4), 5)");
549
System.out.println(result.asDouble()); // 17.0
550
```
551
552
### Guest Objects in Java
553
554
```java
555
Context context = Context.create("js");
556
557
// Create JavaScript object with rich behavior
558
Value jsLibrary = context.eval("js", """
559
({
560
version: '1.0.0',
561
562
users: new Map(),
563
564
addUser: function(id, name, email) {
565
this.users.set(id, {name: name, email: email, created: new Date()});
566
return this.users.get(id);
567
},
568
569
getUser: function(id) {
570
return this.users.get(id);
571
},
572
573
getAllUsers: function() {
574
return Array.from(this.users.values());
575
}
576
})
577
""");
578
579
// Use JavaScript object in Java
580
Value newUser = jsLibrary.invokeMember("addUser", 1, "Alice", "alice@example.com");
581
System.out.println("Created user: " + newUser.getMember("name").asString());
582
583
Value user = jsLibrary.invokeMember("getUser", 1);
584
System.out.println("Retrieved user: " + user.getMember("email").asString());
585
586
Value allUsers = jsLibrary.invokeMember("getAllUsers");
587
System.out.println("Total users: " + allUsers.getArraySize());
588
```
589
590
## Exception Handling
591
592
### Exception Operations
593
594
```java { .api }
595
// Exception handling
596
public boolean isException();
597
public RuntimeException throwException();
598
```
599
600
**Exception Handling Example:**
601
602
```java
603
Context context = Context.create("js");
604
605
try {
606
Value jsError = context.eval("js", """
607
(function() {
608
throw new Error('Something went wrong in JavaScript');
609
})()
610
""");
611
612
if (jsError.isException()) {
613
jsError.throwException(); // Throws PolyglotException
614
}
615
} catch (PolyglotException e) {
616
System.out.println("Caught polyglot exception: " + e.getMessage());
617
if (e.isGuestException()) {
618
Value guestError = e.getGuestObject();
619
System.out.println("Guest error message: " + guestError.getMember("message").asString());
620
}
621
}
622
```
623
624
## Utility Operations
625
626
### Context and Source Information
627
628
```java { .api }
629
// Utility methods
630
public Context getContext();
631
public SourceSection getSourceLocation();
632
public void pin();
633
public static Value asValue(Object o);
634
```
635
636
**Utility Examples:**
637
638
```java
639
Context context = Context.create("js");
640
641
Value jsValue = context.eval("js", "Math.PI");
642
643
// Get associated context
644
Context valueContext = jsValue.getContext();
645
System.out.println("Same context: " + (context == valueContext)); // true
646
647
// Pin value to prevent garbage collection
648
jsValue.pin();
649
650
// Static conversion method
651
Value staticValue = Value.asValue("Hello from static method");
652
```
653
654
## Performance Considerations
655
656
### Value Caching and Reuse
657
658
```java
659
Context context = Context.create("js");
660
661
// Cache frequently accessed values
662
Value jsArrayPrototype = context.eval("js", "Array.prototype");
663
Value pushMethod = jsArrayPrototype.getMember("push");
664
665
// Reuse cached values
666
Value myArray = context.eval("js", "[]");
667
pushMethod.execute(myArray, 1, 2, 3); // Efficient method call
668
```
669
670
### Batch Operations
671
672
```java
673
Context context = Context.create("js");
674
Value jsArray = context.eval("js", "[]");
675
676
// Batch array modifications
677
for (int i = 0; i < 1000; i++) {
678
jsArray.setArrayElement(i, i * i);
679
}
680
681
// More efficient: use JavaScript for bulk operations
682
context.getBindings("js").putMember("data", IntStream.range(0, 1000).toArray());
683
Value processedArray = context.eval("js", "data.map(x => x * x)");
684
```