Stay organized with collections Save and categorize content based on your preferences.

JavaScriptIsolate

public final class JavaScriptIsolate implements 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.

Each isolate object must only be used from one thread.

Summary

Public methods

void

Closes the JavaScriptIsolate object and renders it unusable.

@NonNull ListenableFuture<String>

Evaluates the given JavaScript code and returns the result.

boolean
@RequiresFeature(name = JavaScriptSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER, enforcement = "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
provideNamedData(@NonNull String name, @NonNull byte[] inputBytes)

Provides a byte array for consumption from the JavaScript environment.

Protected methods

void

Public methods

close

public void close()

Closes the JavaScriptIsolate object and renders it unusable. Once closed, no more method calls should be made. Pending evaluations resolve with IsolateTerminatedException immediately.

If isFeatureSupported is true for JS_FEATURE_ISOLATE_TERMINATION, then any pending evaluation is immediately terminated and memory is freed. 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.

evaluateJavaScriptAsync

public @NonNull ListenableFuture<StringevaluateJavaScriptAsync(@NonNull String code)

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 returns a JS String, then the Java Future resolves to Java String.
  • If the JS expression returns a JS Promise, and if isFeatureSupported for JS_FEATURE_PROMISE_RETURN returns true, Java Future resolves to Java String once the promise resolves. If it returns false, then the Future resolves to an empty string.
  • If the JS expression returns another data type, then Java Future resolves to empty Java String.
The environment uses a single JS global object for all the calls to evaluateJavaScriptAsync 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 <script> tags in HTML. The behavior is also similar to evaluateJavascript.

Size of the expression to be evaluated and the result are both limited by the binder transaction limit. Refer android.os.TransactionTooLargeException for more details.

Parameters
@NonNull String code

JavaScript code that is evaluated, it should return a JavaScript String or a Promise of a String in case JS_FEATURE_PROMISE_RETURN is supported

Returns
@NonNull ListenableFuture<String>

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

provideNamedData

@RequiresFeature(name = JavaScriptSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER, enforcement = "androidx.javascriptengine.JavaScriptSandbox#isFeatureSupported")
public boolean provideNamedData(@NonNull String name, @NonNull byte[] inputBytes)

Provides a byte array for consumption from the JavaScript environment. This method provides an efficient way to pass in data from Java into the JavaScript environment which can be referred to from JavaScript. This is more efficient than including data in the JS expression, and allows large data to be sent.

This data can be consumed in the JS environment using android.consumeNamedDataAsArrayBuffer(String) by referring to the data with the name that was used when calling this method. This is a one-time transfer and the calls should be paired.

A single name can only be used once in a particular JavaScriptIsolate. Clients can generate unique names for each call if they need to use this method multiple times. The same name should be included into the JS code.

This API can be used to pass a WASM module into the JS environment for compilation if isFeatureSupported returns true for JS_FEATURE_WASM_COMPILATION. In Java,

    jsIsolate.provideNamedData("id-1", byteArray);
In JS,
    android.consumeNamedDataAsArrayBuffer("id-1").then((value) => {
      return WebAssembly.compile(value).then((module) => {
         ...
      });
    });

The environment uses a single JS global object for all the calls to evaluateJavaScriptAsync and provideNamedData methods.

This method should only be called if isFeatureSupported returns true for JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER.

Parameters
@NonNull String name

Identifier for the data that is passed, the same identifier should be used in the JavaScript environment to refer to the data

@NonNull byte[] inputBytes

Bytes to be passed into the JavaScript environment. This array must not be modified until the JavaScript promise returned by consumeNamedDataAsArrayBuffer has resolved (or rejected).

Returns
boolean

true on success, false if the name has already been used before, in which case the client should use an unused name

Protected methods

finalize

protected void finalize()
Throws
java.lang.Throwable java.lang.Throwable