DEV Community

Cover image for How web browsers work - executing the Javascript (part 5, with illustrations)πŸ’»πŸŒ 
Arika O
Arika O

Posted on • Updated on

How web browsers work - executing the Javascript (part 5, with illustrations)πŸ’»πŸŒ 

While the CSS is being parsed and the CSSOM created, other assets, including JavaScript files, are downloaded. This is happening thanks to the preloader we mentioned in the previous articles.

A preloader is like a parser that scans the HTML file while the main parser is processing the HTML code. Its role is to look for resources like stylesheets, scripts or images (that also need to be retrieved from a server) and request them. Hopefully, by the time the HTML is parsed, those resources are already downloaded and ready to be processed.

5. JAVASCRIPT EXECUTION

So, after we get the Javascript file from the server, the code is interpreted, compiled, parsed and executed. The computer can't understand Javascript code, only the browser can. The JS code needs to be translated into something the computer can work with and this is the job of the Javascript browser engine (not to be confused with the browser engine). Depending on the browser, JS engines can have different names and work differently.

Javascript engines

A javascript engine (sometimes also called an ECMAScript engine) is a piece of software that executes (runs) Javascript code in the browser, and not only (the V8 engine is a core component of the Node.js environment, for example).

JavaScript engines are typically developed by web browser vendors, and every major browser has one. We said the most used browsers as of today are Chrome, Safari, Edge and Firefox. Each one is using a different Javascript engine and these are:

V8
V8 is Google’s high-performance JavaScript engine. It is written in C++ and it's used in Chrome and in Node.js, among others. It implements ECMAScript (a JavaScript standard meant to ensure the interoperability of web pages across different web browsers) and WebAssembley. It implements ​ECMA-262.

JavaScriptCore
JavaScriptCore is the built-in JavaScript engine for WebKit and it powers the Safari browser, Mail and other applications used on macOS. It currently implements ​ECMAScript as in ​ECMA-262 specification. Also it also called SquirrelFish or SquirrelFish Extreme.

Chakra
Chakra is a Javascript engine developed by Microsoft for its Microsoft Edge web browser and other Windows applications. It implements ECMAScript 5.1, and has partial (growing) support for ECMAScript 6. It is written in C++.

SpiderMonkey
SpiderMonkey is Mozilla's Javascript and WebAssembly Engine. It is written in C++, Javascript and Rust and it is used to power Firefox, Servo and other projects.

In the beginning, Javascript engines were simple interpreters. The modern browsers we use today have the capacity to do something called Just-In-Time (JIT) compilation, a mix between compilation and interpretation.

Compilation
During compilation, a piece of software called the compiler takes the code written in a high-level language and converts it into machine code, all at once. An intermediate file (called an object file) is created and that file can run on any machine. After these steps are taken, the code can be executed (imediately after, sometimes in the future or never).

Image description

Interpretation
During interpretation, the interpreter is going through the Javascript code line by line and executes it imediately. No compilation is taking place so no Object Code is created (the output of the code is created by the interpreter itself, using its internal mechanisms). Older versions of Javascript use this type of code execution.
Image description

JIT Compilation
Just in time compilation is a feature of an interpreter for a given language and it tries to take advantage of both compilation and interpretation. Whether during pure compilation, the code is translated before it is executed, in JIT compilation the code is translated while it is being executed (at run time). So we could say that source code is converted to machine code on the fly. Newer versions of Javascript use this type of code execution.

Image description

A very important aspect about JIT compilation is that it will compile the source code into machine code instructions of the running machine. This means that the resulting machine code is optimized for the running machine’s CPU architecture.

In super simple terms, these three processes could be resumed to:

  • Compiler: translates the code
  • Interpreter: runs the code
  • JIT Compiler: translates while running the code

Today, the line between the terms compilation and interpretation has become very blurry so the subject can be extensively debated. If you want to know more about these processes, you could read this article on Mozilla Hacks for starters.

Notice I mentioned older and newer version of Javascript. Browsers that don't support newer versions of the language will interpret the code while the ones that do will use some version of JIT to execute the code (the V8, Chakra JavaScriptCore and SpiderMonkey engines all use JIT). The truth is that even though Javascript is an interpreted language (it does not need compilation), most browsers today will use JIT compilation to run the code, instead of pure interpretation.

How is the Javascript code processed

When Javascript code enters the Javascript engine it gets parsed as a first step. This means the code is read, and while this is happening, the code is transformed into a data structure called the Abstract Syntax Tree (AST). The code will be split into pieces that are relevant to the language (like function or const keywords) and then all these pieces will build the Abstract Synta Tree.

Let's say we have a file containing a program that only does one thing, and that's to define a variable:

const age = 25;
Enter fullscreen mode Exit fullscreen mode

This is how this incredibly super simple line of code would look as an Abstract Syntax Tree (I am using @babel/parser-7.16.12):

Image description

If you want convert some Javascript to an Abstract Syntax Tree yourself, you can use this tool. The AST resulted after writing my varible is actually much bigger and has more nodes that are hidden in the screen shot.

After the AST has been built, it gets translated into machine code and executed right away, since modern Javascript uses Just-In-Time compilation. The execution of this code will be done by the Javascript engine, making use of something called the "call stack".

A call stack is a mechanism for an interpreter (like the JavaScript interpreter in a web browser) to keep track of its place in a script that calls multiple functions β€” what function is currently being run and what functions are called from within that function etc.

Refrence materials:

Discussion (6)

Collapse
gktim profile image
gkTim

Nice articles about how a browser works. Going into detail but not too deep, well explained and with further links if someone want to go into more detail.

Really appreciate your work, thanks for writing this!

Collapse
arikaturika profile image
Arika O Author

Thank you, I'm glad it helped.

Collapse
andrewbaisden profile image
Andrew Baisden

Great article lots of detail.

Collapse
arikaturika profile image
Arika O Author

Thank you. I hope you found it useful.

Collapse
adisoftumag profile image
adisoftUmag

Great series!

Collapse
arikaturika profile image
Arika O Author

I'm glad you like it πŸ™. There will be a few more articles to come.