Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Separate event-loop for same-origin CPU intensive iframe

Let's say I have a CPU intensive iframe.
It's on the same domain as the parent page, thus cross-origin does not apply, so it shares the parent's event-loop.

Is it possible to have a separate JS context (including a separate event-loop) for the iframe, such that it doesn't block the parent's UI?

Setting the sandbox attribute for the iframe tag doesn't solve this, although the docs state that the iframe will be considered to be from a 'unique origin'.

This question is hypothetical/conceptual. I don't have a real use-case for this. Just curious.
I was wandering how sites like JSFiddle run users' code, and apparantly it runs from an iframe from a different domain (jshell.net in JSFiddle's case).

like image 911
EyalAr Avatar asked Jun 23 '14 09:06

EyalAr


People also ask

Is V8 event loop part of?

Since “the event loop” is nothing but a programming pattern, V8 allows the ability to plug-in an external event loop implementation to work with its JavaScript runtime. Using this flexibility, the Chrome browser uses libevent as its event loop implementation, and NodeJS uses libuv to implement the event loop.

What is the precedence in event loop?

The event loop is actually composed of one or more event queues. In each queue, events are handled in a FIFO order. It's up to the browser to decide how many queues to have and what form of prioritisation to give them. There's no Javascript interface to individual event queues or to send events to a particular queue.

What will happen if the call stack and the event loop is empty in node?

When the call stack is empty, the event goes through the event queue and sends the callback to the call stack. The following diagram is a proper representation of the event loop in a Node.

How does event loop decides which function to run next?

The Event Loop takes the timer with the shortest wait time and compares it with the Event Loop's current time. If the wait time has elapsed, then the timer's callback is queued to be called once the call stack is empty. Node. js has different types of timers: setTimeout() and setInterval() .


1 Answers

How do Services like JSFiddle run user code in a different event loop?

They don't resolve the actual problem, they just hack their way around it, by using cross-origin iframes.

For example, this can easily be seen on StackBlitz, they create a subdomain for each execution environment.

On JSFiddle, this is a bit harder to see through at first, since their iframe doesn't have a src attribute set. However, the iframe is bound to a form, which ends up being another cross-origin iframe.

Workaround - Web Workers

As others have mentioned correctly, you can use web workers, to generate a new JS context, and run some heavy calculations there.

This works, since web workers run in isolated threads (MDN).

Workaround - Running code in smaller chunks

As others have mentioned as well, you get a performance increase by running code in smaller chunks. Take the following example:

const array = [ ... ]; // array with hundreds of items
const result = [];

const stepByStepCalculation = () => {
  if (array.length) {
    result.push(doExpensiveCalculation(array[0]));
    array.shift();
    requestAnimationFrame(stepByStepCalculation);
  }
}

stepByStepCalculation();

Now, after every iteration of the event loop, one item of our array is being processed - step by step.

Also, using requestAnimationFrame instead of setInterval or setTimeout has the advantage, that it will be called after every event loop iteration, and not after ~4ms, making it much faster.

The problem with our workarounds

Our workarounds only work, if our expensive tasks, don't have to constantly read from the DOM.

This is a big problem, if our same-origin iframe has expensive JavaScript animations, it will heavily interfere and may cause lags in the UI.

Summarising

Moving calculations into worker threads, or doing them step by step to reduce the load works.

However, to your main question, we can't create a separate JS context (as of right now) for same-origin iframes. Online JS shells tackle this problem by using cross-origin iframes.

It would be interesting to see, if we can somehow run JavaScript code in the compositor or raster thread, since they should have access to our DOM, unlike web workers.

like image 139
Keimeno Avatar answered Nov 03 '22 22:11

Keimeno