public final class Context extends Object implements AutoCloseable
evaluate code.
A polyglot context represents the global runtime state of all installed and permitted languages. Permitted languages are
initialized lazily, when they are used for the first time. For many
context operations, a language identifier needs to be specified. A language identifier is
unique for each language.
Context.eval(Source). This is
possible by evaluating Source objects or a given language identifier and code
String. The evaluation returns either the result value or throws a
PolyglotException if a guest language error occurs.
Example for evaluation of a fragment of JavaScript code with a new context:
Context context = Context.create();
Value result = context.eval("js", "42");
assert result.asInt() == 42;
context.close();
In this example:
initialized.
int
.
AutoCloseable for use with the Java
try-with-resources statement.
Contexts may be created either with default configuration using the create method or with custom configuration using the builder.
Both methods allow to specify a subset of the installed languages as permitted languages. If no
language is specified then all installed languages are permitted. Using the builder method
input, error and
output streams, options,
and application arguments may be configured.
Options may be specified for languages,
instruments, the engine and the
compiler. For language options, the
option key consists of the language id plus a dot followed by the option
name (e.g. "js.Strict"). For most languages the option names start with an upper-case letter by
convention. A list of available options may be received using Language.getOptions().
Instrument options are structured in the same way as language
options but start with the instrument id instead.
If system properties are enabled, which they
are by default, then all polyglot options maybe specified with the prefix "polyglot." (e.g.
"-Dpolyglot.js.Strict=true"). The system properties are read only once when the context or engine
instance is created. After that, changes to the system properties have no affect.
Each Graal language performs an initialization step before it can be used to execute code, after
which it remains initialized for the lifetime of the context. Initialization is by default lazy
and automatic, but initialization can be forced manually if
needed.
Example for custom configuration using the context builder:
OutputStream myOut = new BufferedOutputStream()
Context context = Context.newBuilder("js", "R")
.out(myOut)
.option("js.Strict", "true")
.allowAllAccess(true)
.build();
context.eval("js", "42");
context.eval("R", "42");
context.close();
In this example:
Context.Builder.allowAllAccess(boolean) we grant a new context instance with the same
access privileges as the host virtual machine.
initialized as well.
AutoCloseable for use with the Java try-with-resources
statement.
language bindings. Each language provides its own bindings object
for a context. The bindings object may be used to read, modify, insert and delete members in the
top-most scope of the language. Certain languages may not allow write access to the bindings
object. See Context.getBindings(String) for details.
A context instance also provides access to the polyglot bindings.
The polyglot bindings are shared between languages and may be used to exchange values. See
Context.getPolyglotBindings() for details.
Examples using language bindings from JavaScript:
Context context = Context.create("js");
Value jsBindings = context.getBindings("js")
jsBindings.putMember("foo", 42);
assert context.eval("js", "foo").asInt() == 42;
context.eval("js", "var bar = 42");
assert jsBindings.getMember("bar").asInt() == 42;
assert jsBindings.getMember("Math")
.getMember("abs")
.execute(-42)
.asInt() == 42;
context.close();
In this example:
jsBindings.
foo into to the bindings object and verify that the
object is accessible within the language by reading from a global symbol with the same name.
Math.abs symbol and execute
it with -42. This result is asserted to be 42.
Context.asValue(Object).
Also see Value.as(Class) for further details.
By default only public classes, methods, and fields that are annotated with
@HostAccess.Export are accessible to the guest language. This policy
can be customized using Context.Builder.allowHostAccess(HostAccess) when constructing the
context.
Example using a Java object from JavaScript:
public class JavaRecord {
@HostAccess.Export public int x;
@HostAccess.Export
public String name() {
return "foo";
}
}
Context context = Context.create();
JavaRecord record = new JavaRecord();
context.getBindings("js").putMember("javaRecord", record);
context.eval("js", "javaRecord.x = 42");
assert record.x == 42;
context.eval("js", "javaRecord.name()").asString().equals("foo");
Context and Value API throw a
PolyglotException in case an error occurs. See PolyglotException for further
details on error handling.
all access must be set to true.
Contexts can be configured to share certain system resources
like ASTs or optimized code by specifying a single underlying engine. See Engine for more
details about code sharing.
Context can be configured to allow value sharing between multiple contexts (allowed by default).
See Context.Builder.allowValueSharing(boolean) for details.
proxy interfaces allow to mimic guest language objects, arrays, executables,
primitives and native objects in Graal languages. Every Graal language will treat proxy instances
like objects of that particular language. Multiple proxy interfaces can be implemented at the
same time. For example, it is useful to provide proxy values that are objects with members and
arrays at the same time.
IllegalStateException is thrown by the accessing
method.
Meta-data from the context's underlying engine can be retrieved safely by
any thread at any time.
A context may be closed from any thread, but only if the context is not
currently executing code. If the context is currently executing some code, a different thread may
kill the running execution and close the context using Context.close(boolean).
The context pre-initialization is enabled by setting the system property
polyglot.image-build-time.PreinitializeContexts to a comma separated list of language ids
which should be pre-initialized, for example:
-Dpolyglot.image-build-time.PreinitializeContexts=js,python
See
com.oracle.truffle.api.TruffleLanguage.patchContext(java.lang.Object, com.oracle.truffle.api.TruffleLanguage.Env)
for details about pre-initialization for language implementers.
| Modifier and Type | Class and Description |
|---|---|
class |
Context.Builder
Builder class to construct
Context instances. |
| Modifier and Type | Method and Description |
|---|---|
Value |
asValue(Object hostValue)
Converts a host value to a polyglot
value representation. |
void |
close()
Closes this context and frees up potentially allocated native resources.
|
void |
close(boolean cancelIfExecuting)
Closes the context and frees up potentially allocated native resources.
|
static Context |
create(String... permittedLanguages)
Creates a context with default configuration.
|
void |
enter()
Explicitly enters the context on the current thread.
|
boolean |
equals(Object obj) |
Value |
eval(Source source)
Evaluates a source object by using the language specified
in the source.
|
Value |
eval(String languageId,
CharSequence source)
Evaluates a guest language code literal, using a provided
language
id. |
Value |
getBindings(String languageId)
Returns a value that represents the top-most bindings of a language.
|
static Context |
getCurrent()
Returns the currently entered polyglot context.
|
Engine |
getEngine()
Provides access to meta-data about the underlying Graal engine.
|
Value |
getPolyglotBindings()
Returns polyglot bindings that may be used to exchange symbols between the host and guest
languages.
|
int |
hashCode() |
boolean |
initialize(String languageId)
Forces the initialization of a language.
|
void |
interrupt(Duration timeout)
Use this method to interrupt this context.
|
void |
leave()
Explicitly leaves the context on the current thread.
|
static Context.Builder |
newBuilder(String... permittedLanguages)
Creates a builder for constructing a context with custom configuration.
|
Value |
parse(Source source)
|
Value |
parse(String languageId,
CharSequence source)
Parses but does not evaluate a guest language code literal using a provided
language id and character sequence and returns a value
that can be executed. |
void |
resetLimits()
Resets all accumulators of resource limits for the associated context to zero.
|
void |
safepoint()
Polls safepoints events and executes them for the current thread.
|
public Engine getEngine()
Engine being used by this contextpublic Value eval(Source source)
value and never returns
null. The first time a source is evaluated, it will be parsed. Consecutive
invocations of eval with the same source will only execute the already parsed code.
Basic Example:
try (Context context = Context.create()) {
Source source = Source.newBuilder("js", "42", "mysource.js").build();
Value result = context.eval(source);
assert result.asInt() == 42;
}
source - a source object to evaluatenull, but the
result might represent a null value.PolyglotException - in case the guest language code parsing or evaluation failed.IllegalStateException - if the context is already closed and the current thread is not
allowed to access it.IllegalArgumentException - if the language of the given source is not installed or the
MIME type is not supported with the language.public Value eval(String languageId, CharSequence source)
language
id. The result is accessible as value and never returns null. The
provided CharSequence must represent an immutable String.
Basic Example:
try (Context context = Context.create()) {
Value result = context.eval("js", "42");
assert result.asInt() == 42;
}
null, but the
result might represent a null value.PolyglotException - in case the guest language code parsing or evaluation failed.IllegalArgumentException - if the language does not exist or is not accessible.IllegalStateException - if the context is already closed and the current thread is not
allowed to access it, or if the given language is not installed.public Value parse(Source source) throws PolyglotException
value that can be
executed. If a parsing fails, e.g. due to a syntax error in
the source, then a PolyglotException will be thrown. In case of a syntax error the
PolyglotException.isSyntaxError() will return true. There is no
guarantee that only syntax errors will be thrown by this method. Any other guest language
exception might be thrown. If the validation succeeds then the method completes without
throwing an exception.
The result value only supports an empty set of arguments to execute. If executed repeatedly then the source is evaluated multiple times.
Interactive sources will print their result for
each execution of the parsing result to the output stream.
If the parsing succeeds and the source is cached then
the result will automatically be reused for consecutive calls to Context.parse(Source) or
Context.eval(Source). If the validation should be performed for each invocation or the
result should not be remembered then cached can be set
to false. By default sources are cached.
Basic Example:
try (Context context = Context.create()) {
Source source = Source.create("js", "42");
Value value;
try {
value = context.parse(source);
// parsing succeeded
} catch (PolyglotException e) {
if (e.isSyntaxError()) {
SourceSection location = e.getSourceLocation();
// syntax error detected at location
} else {
// other guest error detected
}
throw e;
}
// evaluate the parsed script
value.execute();
}
source - a source object to parsePolyglotException - in case the guest language code parsing or validation failed.IllegalArgumentException - if the language does not exist or is not accessible.IllegalStateException - if the context is already closed and the current thread is not
allowed to access it, or if the given language is not installed.public Value parse(String languageId, CharSequence source)
language id and character sequence and returns a value
that can be executed. The provided CharSequence must
represent an immutable String. This method represents a short-hand for Context.parse(Source)
.
The result value only supports an empty set of arguments to execute. If executed repeatedly then the source is evaluated multiple times.
Interactive sources will print their result for
each execution of the parsing result to the output stream.
try (Context context = Context.create()) {
Value value;
try {
value = context.parse("js", "42");
// parsing succeeded
} catch (PolyglotException e) {
if (e.isSyntaxError()) {
SourceSection location = e.getSourceLocation();
// syntax error detected at location
} else {
// other guest error detected
}
throw e;
}
// evaluate the parsed script
value.execute();
}
PolyglotException - in case the guest language code parsing or evaluation failed.IllegalArgumentException - if the language does not exist or is not accessible.IllegalStateException - if the context is already closed and the current thread is not
allowed to access it, or if the given language is not installed.public Value getPolyglotBindings()
members and its members are
readable, writable
and removable.
Guest languages may put and get members through language specific APIs. For example, in
JavaScript, symbols of the polyglot bindings can be accessed using
Polyglot.import("name") and set using
Polyglot.export("name", value). Please see the individual language reference on
how to access these symbols.
IllegalStateException - if context is already closed.public Value getBindings(String languageId)
member for a symbol in the scope.
Languages may allow modifications of members of the returned bindings object at the
language's discretion. If the language has not been initialized
yet, it will be initialized when the bindings are requested.IllegalArgumentException - if the language does not exist or is not accessible.IllegalStateException - if the context is already closed.PolyglotException - in case the lazy initialization failed due to a guest language
error.public boolean initialize(String languageId)
languageId - the identifier of the language to initialize.true if the language was initialized. Returns false if it
was already initialized.PolyglotException - in case the initialization failed due to a guest language error.IllegalArgumentException - if the language does not exist or is not accessible.IllegalStateException - if the context is already closed.public void resetLimits()
public Value asValue(Object hostValue)
value representation. This conversion is
applied implicitly whenever execution or
instantiation arguments are provided,
members and
array elements are set or when a value is
returned by a polyglot proxy. It is not required nor efficient to explicitly
convert to polyglot values before performing these operations. This method is useful to
convert a mapped host value back to a polyglot value while preserving
the identity.
When a host value is converted to a polyglot value the following rules apply:
hostValue is null, then it will be interpreted as
polyglot null.
hostValue is already a polyglot value, then it will be
cast to Value.
hostValue is an instance of Byte, Short,
Integer, Long, Float or Double, then it will be interpreted
as polyglot number. Other subclasses of Number will be
interpreted as host object (see later).
hostValue is an instance of Character or String, then
it will be interpreted as polyglot string.
hostValue is an instance of Boolean, then it will be
interpreted as polyglot boolean.
hostValue is an instance of Instant, LocalTime,
ZonedDateTime, Date but not Date or
Time then it will be interpreted as polyglot time.
hostValue is an instance of Instant, LocalDate,
ZonedDateTime, Date but not Time or
Date then it will be interpreted as polyglot date.
hostValue is an instance of ZoneId, Instant,
ZonedDateTime, Date but not Time and
Date then it will be interpreted as polyglot time
zone.
hostValue is an instance of ZonedDateTime, Instant,
ZonedDateTime, Date but not Time and
Date then it will be interpreted as polyglot instant.
hostValue is an instance of Duration then it will be
interpreted as polyglot duration.
hostValue is a polyglot proxy, then it will be
interpreted according to the behavior specified by the proxy. See the javadoc of the proxy
subclass for further details.
hostValue is a non-primitive mapped Java
value, then the original value will be restored. For example, if a guest language object was
mapped to Map, then the original object identity will be preserved when converting
back to a polyglot value.
hostValue will be interpreted as host
object. Host objects expose all their public java fields and methods as
members. In addition, Java arrays, subtypes of List
and Map.Entry will be interpreted as a value with array
elements. The subtypes of Iterable will be interpreted as a value with
Value.hasIterator() iterator}. The subtypes of Iterator will be interpreted
as an iterator value. The subtypes of Map will be
interpreted as a value with Value.hasHashEntries() hash entries}. And single method
interfaces annotated with FunctionalInterface are executable directly. Java Class instances are interpreted as
instantiable, but they do not expose Class methods as members.
Basic Examples: The following assertion statements always hold:
Context context = Context.create();
assert context.asValue(null).isNull();
assert context.asValue(42).isNumber();
assert context.asValue("42").isString();
assert context.asValue('c').isString();
assert context.asValue(new String[0]).hasArrayElements();
assert context.asValue(new ArrayList<>()).isHostObject();
assert context.asValue(new ArrayList<>()).hasArrayElements();
assert context.asValue((Supplier) () -> 42).execute().asInt() == 42;
members. Methods and fields are grouped by name,
so only one member is exposed for each name.
Class objects have a member named static referring to the class's companion
object containing the static methods of the class. Likewise, the companion object has a
member named class that points back to the class object.
When an argument value needs to be mapped to match a required Java method parameter type,
then the semantics of host value mapping is used. The result of the
mapping is equivalent of calling Value.as(Class) with the parameter type. Therefore,
a ClassCastException or NullPointerException is thrown if a parameter value
cannot be cast to the required parameter type.
Overloaded java methods are selected based on the provided arguments. In case multiple mapped
Java methods with the same name are applicable for executions or instantiations, then the method with the
most concrete method with applicable arguments will be called.
The following parameter type hierarchy is used for a method resolution. Left-most parameter types are prioritized over types to their right.
Boolean values: boolean, Boolean, Object
Advanced Example:
This example first creates a new instance of the Java class Record and inspects
it using the polyglot value API. Later, a host value is converted to a polyglot value using
JavaScript guest language.
In the following examples all assertions hold.
class JavaRecord {
public int x = 42;
public double y = 42.0;
public String name() {
return "foo";
}
}
Context context = Context.create();
Value record = context.asValue(new JavaRecord());
assert record.getMember("x").asInt() == 42;
assert record.getMember("y").asDouble() == 42.0d;
assert record.getMember("name").execute().asString().equals("foo");
assert context.eval("js", "(function(record) record.x)")
.execute(record).asInt() == 42;
assert context.eval("js", "(function(record) record.y)")
.execute(record).asDouble() == 42.0d;
assert context.eval("js", "(function(record) record.name())")
.execute(record).asString().equals("foo");
hostValue - the host value to convert to a polyglot value.IllegalStateException - if the context is already closedValue.as(Class)public void enter()
execute method. This can be inefficient if a very high
number of simple operations needs to be performed. By entering and
leaving once explicitly, the overhead for entering/leaving the context for
each operation can be eliminated. Contexts can be entered multiple times on the same thread.IllegalStateException - if the context is already closed.PolyglotException - if a language has denied execution on the current thread.leave a context.public void leave()
entered before calling this method.IllegalStateException - if the context is already closed or if the context was not
entered on the current thread.enter a context.public void close(boolean cancelIfExecuting)
PolyglotException. The exception indicates that it was
cancelled. Please note, canceling a single context
can negatively affect the performance of other executing contexts constructed with the same
engine.
If internal errors occur during context closing, then they are printed to the configured
error output stream. If a context was closed, then its
methods will throw an IllegalStateException when invoked. If an attempt to close a
context was successful, then consecutive calls to close have no effect.
For convenience, before the actual closing process begins, the close method leaves the
context on the current thread, if it was entered explicitly.
cancelIfExecuting - if true then currently executing contexts will be
cancelled, else an
IllegalStateException is thrown.PolyglotException - in case the close failed due to a guest language error.IllegalStateException - if the context is still running and cancelIfExecuting is
falseclose an engine.public void close()
IllegalStateException is thrown. To close concurrently executing contexts see
Context.close(boolean).
If internal errors occur during the context closure, then they are printed to the configured
error output stream. If a context was closed, then its
methods will throw an IllegalStateException, when invoked. If an attempt to close a
context was successful, then consecutive calls to close have no effect.
For convenience, before the actual closing process begins, the close method leaves the
context on the current thread, if it was entered explicitly.
close in interface AutoCloseablePolyglotException - in case the close failed due to a guest language error.IllegalStateException - if the context is currently executing on another thread.close an engine.public void interrupt(Duration timeout) throws TimeoutException
close(true) is executed.timeout - specifies the duration the interrupt method will wait for the active threads
of the context to be finished. Setting the duration to 0
means wait indefinitely.IllegalStateException - in case the context is entered in the current thread.TimeoutException - in case the interrupt was not successful, i.e., not all threads were
finished within the specified time limit.public void safepoint()
In this example we allow interruption and
cancellation to stop the processing of our event queue.
class EventProcessor {
ListPolyglotException - in case the close failed due to a guest language error.IllegalStateException - if the context is already closed.public static Context getCurrent()
Context.enter() on the current thread. The returned context may be
used to:
string literals or
file sources.
Convert Java values to polyglot values.
bindings of other languages.
polyglot bindings.
languages or
options of the engine.
The returned context can not be used to enter , leave or close the context or engine. Invoking such
methods will cause an IllegalStateException to be thrown. This ensures that only the
creator of a context is allowed to enter, leave or close a
context.
The current entered context may change. It is therefore required to call getCurrent every time a context is needed. The current entered context should not be cached
in static fields.
IllegalStateException - if no context is currently entered.public static Context create(String... permittedLanguages)
permittedLanguages - names of languages permitted in this context. If no languages are
provided, then all installed languages will be permitted.public static Context.Builder newBuilder(String... permittedLanguages)
permittedLanguages - names of languages permitted in the context. If no languages are
provided, then all installed languages will be permitted.