Today we look at a new JavaScript
proposal into statge3
: the ShadowRealm API
.
JavaScript runtime environment
realm
, a rather abstract word, actually represents a JavaScript
independent runtime environment with independent variable scopes.
For example, the following code.
Each iframe
has a separate runtime environment, the global object of document
is different from the global object of iframe
, and similarly, the Array
on the global object must be different as well.
ShadowRealm API
The ShadowRealm API
is a new JavaScript
proposal that allows a JS runtime to create multiple highly isolated JS runtime environments (realm
), each realm
with independent global objects and built-in objects.
ShadowRealm has the following type signature.
Each ShadowRealm
instance has its own separate runtime environment, which provides two ways for us to execute the code in the runtime environment.
.evaluate()
: synchronizes the execution of the code string, similar toeval()
..importValue()
: returns aPromise
object that executes the code string asynchronously.
shadowRealm.evaluate()
Type signature of .evaluate()
.
|
|
.evaluate()
works much like eval()
.
But unlike eval()
, the code is executed in a separate runtime environment from .evaluate()
.
If .evaluate()
returns a function, this function is wrapped for ease of calling externally and then run in ShadowRealm
.
Whenever a value is passed into ShadowRealm
, it must be of primitive type or callable. Otherwise, an exception will be thrown.
shadowRealm.importValue()
Type signature of .importValue()
|
|
You can directly import an external module that executes asynchronously and returns a Promise
, as follows.
|
|
As with .evaluate()
, the values passed into ShadowRealms
(both the arguments and the result of the cross-environment function call) must be raw or callable.
What can ShadowRealms be used for?
- Run third-party code such as plug-ins in programs such as
Web IDE
orWeb
drawing applications. - Create a programming environment in
ShadowRealms
to run user code. - The server can run third-party code in
ShadowRealms
. - Tests can be run in ShadowRealms so that the external JS execution environment is not affected and each suite can be launched in the new environment (this helps with reusability).
- Web crawling (extracting data from web pages) and web application testing, etc. can be run in
ShadowRealms
.
Comparison with other solutions
eval() and Function
ShadowRealms
is much like eval()
and Function
, but a little better than both of them: we can create new JS runtime environments and execute code in them, which protects the external JS runtime environment from the operations executed by the code.
Web Workers
Web Worker
is a more powerful isolation mechanism than ShadowRealms
. The code in it runs in a separate process and communication is asynchronous.
However, when we want to do some more lightweight operations, ShadowRealms
is a good choice. Its algorithm allows simultaneous computation, is more convenient, and the global data management is more free.
iframe
As we mentioned before, each iframe
has its own runtime environment in which we can execute code synchronously.
Compared to ShadowRealms
, it still has the following disadvantages.
- Can only use
iframe
in the browser. - The need to add an
iframe
to theDOM
to initialize it. - Each
iframe
environment contains the full DOM, which limits the flexibility of customization in some scenarios. - By default, objects are cross-environmental, which means extra work is needed to ensure code security.
The vm module on Node.js
The vm
module for Node.js
is similar to the ShadowRealm API
, but has more features: caching the JavaScript
engine, intercepting import()
, and so on. But its only drawback is that it is not cross-platform and can only be used in the Node.js
environment.
Usage Example: Running Tests in ShadowRealms
Here we see a small Demo
for running tests in ShadowRealms
. The test library collects the tests specified by test()
and allows us to run them via runTests()
.
|
|
Use the library to specify the test.
In the next example, we dynamically load the my-test.js
module to collect and then run tests.
Alas, there is currently no way to load the module without importing anything.
That’s why there is a default export in the last line of the previous example. We use the ShadowRealm.importvalue()
method to import the default export
.
|
|
Running Web Applications in ShadowRealms
The jsdom
library creates a wrapped browser environment that can be used to test Web
applications, extract data from HTML
, and more. It currently uses the Node.js vm
module, and may be updated to use ShadowRealms
in the future (the latter has the benefit of being cross-platform, while vm
currently only supports Node.js
).