@ThreadSafe
class JavaScriptIsolate : AutoCloseable

Environment within a JavaScriptSandbox where JavaScript is executed.

A single JavaScriptSandbox process can contain any number of JavaScriptIsolate instances where JS can be evaluated independently and in parallel.

Each isolate has its own state and JS global object, and cannot interact with any other isolate through JS APIs. There is only a moderate security boundary between isolates in a single JavaScriptSandbox. If the code in one JavaScriptIsolate is able to compromise the security of the JS engine then it may be able to observe or manipulate other isolates, since they run in the same process. For strong isolation multiple JavaScriptSandbox processes should be used, but it is not supported at the moment. Please find the feature request here.

This class is thread-safe.

Summary

Public functions

Unit

Add a callback to listen for isolate crashes.

Unit
addOnTerminatedCallback(
    executor: Executor,
    callback: Consumer<TerminationInfo!>
)

Add a callback to listen for isolate crashes.

Unit
@RequiresFeature(name = JavaScriptSandbox.JS_FEATURE_CONSOLE_MESSAGING, enforcement = "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
clearConsoleCallback()

Clear any JavaScriptConsoleCallback set via setConsoleCallback.

Unit

Closes the JavaScriptIsolate object and renders it unusable.

ListenableFuture<String!>
@RequiresFeature(name = JavaScriptSandbox.JS_FEATURE_EVALUATE_FROM_FD, enforcement = "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
evaluateJavaScriptAsync(afd: AssetFileDescriptor)

Reads and evaluates the JavaScript code in the file described by the given AssetFileDescriptor.

ListenableFuture<String!>

Evaluates the given JavaScript code and returns the result.

ListenableFuture<String!>
@RequiresFeature(name = JavaScriptSandbox.JS_FEATURE_EVALUATE_FROM_FD, enforcement = "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
evaluateJavaScriptAsync(pfd: ParcelFileDescriptor)

Reads and evaluates the JavaScript code in the file described by the given ParcelFileDescriptor.

Unit
@RequiresFeature(name = JavaScriptSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER, enforcement = "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
provideNamedData(name: String, inputBytes: ByteArray)

Provides a byte array for consumption from the JavaScript environment.

Unit

Remove a callback previously registered with addOnTerminatedCallback.

Unit
@RequiresFeature(name = JavaScriptSandbox.JS_FEATURE_CONSOLE_MESSAGING, enforcement = "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
setConsoleCallback(callback: JavaScriptConsoleCallback)

Set a JavaScriptConsoleCallback to process console messages from the isolate.

Unit
@RequiresFeature(name = JavaScriptSandbox.JS_FEATURE_CONSOLE_MESSAGING, enforcement = "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
setConsoleCallback(
    executor: Executor,
    callback: JavaScriptConsoleCallback
)

Set a JavaScriptConsoleCallback to process console messages from the isolate.

Protected functions

Unit

Public functions

addOnTerminatedCallback

Added in 1.0.0-rc01
fun addOnTerminatedCallback(callback: Consumer<TerminationInfo!>): Unit

Add a callback to listen for isolate crashes.

This is the same as calling addOnTerminatedCallback using the main executor of the context used to create the JavaScriptSandbox object.

Parameters
callback: Consumer<TerminationInfo!>

the consumer to be called with TerminationInfo when a crash occurs

Throws
java.lang.IllegalStateException

if the callback is already registered (using any executor)

addOnTerminatedCallback

Added in 1.0.0-rc01
fun addOnTerminatedCallback(
    executor: Executor,
    callback: Consumer<TerminationInfo!>
): Unit

Add a callback to listen for isolate crashes.

There is no guaranteed order to when these callbacks are triggered and unfinished evaluations' futures are rejected.

Registering a callback after the isolate has crashed will result in it being executed immediately on the supplied executor with the isolate's TerminationInfo as an argument.

Closing an isolate via close is not considered a crash, even if there are unresolved evaluations, and will not trigger termination callbacks.

Parameters
executor: Executor

the executor with which to run callback

callback: Consumer<TerminationInfo!>

the consumer to be called with TerminationInfo when a crash occurs

Throws
java.lang.IllegalStateException

if the callback is already registered (using any executor)

clearConsoleCallback

Added in 1.0.0-rc01
@RequiresFeature(name = JavaScriptSandbox.JS_FEATURE_CONSOLE_MESSAGING, enforcement = "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
fun clearConsoleCallback(): Unit

Clear any JavaScriptConsoleCallback set via setConsoleCallback.

Clearing a callback is not guaranteed to take effect for any already pending evaluations.

close

Added in 1.0.0-rc01
fun close(): Unit

Closes the JavaScriptIsolate object and renders it unusable.

Once closed, no more method calls should be made. Pending evaluations will reject with an IsolateTerminatedException immediately.

If isFeatureSupported is true for JS_FEATURE_ISOLATE_TERMINATION, then any pending evaluations are terminated. If it is false, the isolate will not get cleaned up until the pending evaluations have run to completion and will consume resources until then.

Closing an isolate via this method does not wait on the isolate to clean up. Resources held by the isolate may remain in use for a duration after this method returns.

evaluateJavaScriptAsync

Added in 1.0.0-rc01
@RequiresFeature(name = JavaScriptSandbox.JS_FEATURE_EVALUATE_FROM_FD, enforcement = "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
fun evaluateJavaScriptAsync(afd: AssetFileDescriptor): ListenableFuture<String!>

Reads and evaluates the JavaScript code in the file described by the given AssetFileDescriptor.

Please refer to the documentation of evaluateJavaScriptAsync as the behavior of this method is similar other than for the input type.

This API exposes the underlying file to the service. In case the service process is compromised for unforeseen reasons, it might be able to read from the AssetFileDescriptor beyond the given length and offset. This API does not close the given AssetFileDescriptor.

Note: The underlying file data must be UTF-8 encoded.

This overload is useful when the source of the data is easily readable as an AssetFileDescriptor, e.g. an asset or raw resource.

Parameters
afd: AssetFileDescriptor

an AssetFileDescriptor for a file containing UTF-8 encoded JavaScript code to be evaluated

Returns
ListenableFuture<String!>

a Future that evaluates to the result String of the evaluation or an exception (see JavaScriptException and subclasses) if there is an error

evaluateJavaScriptAsync

Added in 1.0.0-rc01
fun evaluateJavaScriptAsync(code: String): ListenableFuture<String!>

Evaluates the given JavaScript code and returns the result.

There are 3 possible behaviors based on the output of the expression:

  • If the JS expression evaluates to a JS String, then the Java Future resolves to a Java String.
  • If the JS expression evaluates to a JS Promise, and if isFeatureSupported for JS_FEATURE_PROMISE_RETURN returns true, the Java Future resolves to a Java String once the promise resolves. If it returns false, then the Future resolves to an empty Java string.
  • If the JS expression evaluates to another data type, then the Java Future resolves to an empty Java String.
The environment uses a single JS global object for all the calls to evaluateJavaScriptAsync(String) and provideNamedData methods. These calls are queued up and are run one at a time in sequence, using the single JS environment for the isolate. The global variables set by one evaluation are visible for later evaluations. This is similar to adding multiple