DEV Community

Cover image for Finally, JavaScript is Getting Matured with ShadowRealms
Jigar Shah
Jigar Shah

Posted on

Finally, JavaScript is Getting Matured with ShadowRealms

JavaScript has recently come up with three unique features that define JavaScript's very bright future. And here I am going to talk about one of them - ShadowRealms.

Future JavaScript consists of:

  • JavaScript Pipeline Operators
  • Records and Tuples
  • ShadowRealms However, I may discuss the first and second features later on. Maybe in the next blog series.

So, let’s understand what ShadowRealms is. I seriously can’t wait for this one because it looks like JavaScript is finally becoming the mature environment we need.

What is ShadowRelams?

ShadowRealm is another amazing feature of JavaScript, which will blow the mind of every JavaScript developer in the industry. The ShadowRealm will help us create an independent global context from which we can execute the JavaScript code file.

So, now you have understood what ShadowRealm is. So, let’s move ahead to understand how ShadowRealm works.

ShadowRealms Support
ShadowRealms is one of the emerging concepts of JavaScript, which is in Phase 3 development. As a result, many browsers or native server-side languages like NodeJs don’t support ShadowRealms. Furthermore, there’s no stable babel or npm plugin to polyfill the functionality due to the many modifications over the years.

Since the ShadowRealm has reached Phase 3, I am hoping to see no more modifications in the coming days. Also, I am expecting ShadowRealms to have native support at some time.

The Functionality of ShadowRealms
A ShadowRealm is essentially a technique to create a whole new environment with a unique global object that separates the code from other realms. In JavaScript, if I talk about a global object, it’s about the concept of window or globalThis.
The primary goal of ShadowRealm is to eliminate the conflict between many codebases and create a secure environment to execute code that needs to be executed in isolation. It means we can observe less pollution in the global object from other codebase or packages. As a result, code in a ShadowRealm is unable to transfer or interact with other objects in different realms.

Use Cases of ShadowRealms
Just like JavaScript, ShadowRealms execute on the same thread. So, we need to use Web Workers in order to multi-thread our JavaScript. As a result, we can find a ShadowRealm in both a worker and a conventional JavaScript file. ShadownRealms can also exist within other ShadowRealms.
We don't want code editors that interact with the main homepage to interact with the user.
We need plugins that can be run on their own.
Emulating the DOM in a distinct environment. For example, we could emulate ShadowRealm if we need to find out the scroll position for the particular area. It means the user scrolling on the main web page doesn’t influence the window.top variable in our emulation.

How to Create a ShadowRealm in JavaScript?

Now is the time to work as a JavaScript developer and see how ShadowRealm looks in code.

First of all, we have to call a new ShadowRealm instance. Then import some JS into our Realm, which will be executed within it. And for that, we are using importValue function. This function works as effectively as the import function.

let myRealm = new ShadowRealm(); 

let myFunction = await myRealm.importValue('./function-script.js', 'analyseFiles'); 
// Now we can execute our function within our ShadowRealm 
let fileAnalysis = myFunctions();
Enter fullscreen mode Exit fullscreen mode

As we can see in the above example, the export name analyseFiles is what we're importing from function-script.js. This export is then captured and saved in myFunction. Importantly, the export we add into our domain must be callable, which means it must be a function that we can execute.

Our function-script.js file is nothing more than a standard JavaScript file with an export.

This is what it might look like:

export function analyseFiles() 
{ 
    console.log('Hello, Developer!'); 
}
Enter fullscreen mode Exit fullscreen mode

The ShadowRealm exists independently of any other global objects we might have, such as window or globalThis.

We can use the curly bracket import notation in the same way we do with other imports:

let myRealm = new ShadowRealm(); 

const { runFunction, testFunction, createFunction } = await myRealm.importValue('./function-script.js'); 

let fileAnalysis = runFunction();
Enter fullscreen mode Exit fullscreen mode

If we wish to use importValues, we can build numerous promises that all convert into an array.

let myRealm = new ShadowRealm(); 

const [ runFunction, testFunction, createFunction ] = await Promise.all([ 

    myRealm.importValue('./file-one.js', 'runFunction'), 

    myRealm.importValue('./file-two.js', 'testFunction'), 

    myRealm.importValue('./file-three.js', 'createFunction'), 

]); 

let fileAnalysis = runFunction();
Enter fullscreen mode Exit fullscreen mode

How to Execute Code with evaluate in ShadowRealms
We can use the evaluate method to execute a string on our ShadowRealm of JavaScript if we need to run code directly in a ShadowRealm that comes from the same file but not another one. This works similarly to eval():

let myRealm = new ShadowRealm(); 
myRealm.evaluate(`console.log(‘Hello, Developer!')`);
Enter fullscreen mode Exit fullscreen mode

ShadowRealm importValue is thennable
The value of ImportValues is thennable because it returns a promise. That implies we can surely utilize then() on it and then try the output function it produces to do something.

Consider the following scenario:

window.myVariable = 'Hello, Developer!'; 
let myRealm = new ShadowRealm(); 

myRealm.importValue('someFile.js', 'createFunction').then((createFunction) => { 

   // Do something with createFunction(); 
})
Enter fullscreen mode Exit fullscreen mode

You can also use this technique to access global variables declared in someFile.js.

Let's imagine we altered someFile.js to something like this:

globalThis.name = "fjolt"; 
export function returnGlobals(property) 
{ 
  return globalThis[property]; 
}
Enter fullscreen mode Exit fullscreen mode

Now, in our then function, we could get the value of globalThis.name:

window.myVariable = 'Hello, Developer!'; 
let myRealm = new ShadowRealm();

myRealm.importValue('someFile.js', 'returnGlobals').then((returnGlobals) => { 

    // Do something with returnGlobals(); 

    console.log(returnGlobals("name")); // Returns fjolt 
    console.log(window.myVariable); // Returns undefined 
})
Enter fullscreen mode Exit fullscreen mode

Is JavaScript Getting Matured?

Nowadays, iframe has been the most common approach to separate web environments. While talking about iframes, they are cumbersome and inconvenient to use. On the other hand, ShadowRealms are more efficient, easier to integrate with our existing codebase, and compatible with modern JavaScript technologies such as Web Workers.
ShadowRealms will very certainly become a standard for JavaScript development due to their unique value proposition of offering a separate area for code execution that does not interact with the rest of the codebase.
They could become a useful mechanism for packages and modules to export their contents without worrying about other sections of the code base interfering.
As a result, I expect to see them in the future. Until then, happy coding and keep watching this space for more technology-driven content.

Top comments (0)

The discussion has been locked. New comments can't be added.