tech-blog-final.jpg
Blog

Behind the Scenes of Node.js: The Scope of V8’s Engine

What is Node.js?

Node.js is an open-source runtime environment that allows developers to build server-side applications using JavaScript. It’s built on the V8 JavaScript engine and provides an event-driven, non-blocking I/O model, which makes it well-suited for building scalable and high-performance network applications.

Let's negate certain elements mentioned in the preceding paragraph., 

Node.js is an open-source runtime environment that allows developers to build server-side applications using JavaScript. It’s built on the V8 JavaScript engine and provides an event-driven, non-blocking I/O model, which makes it well-suited for building scalable and high-performance network applications.

Excellent! Let's now spotlight the key features of Node.js.

Node.js is an open-source runtime environment that allows developers to build server-side applications using JavaScriptIt’s built on the V8 JavaScript engine and provides an event-driven, non-blocking I/O modelwhich makes it well-suited for building scalable and high-performance network applications.

That's truly fantastic! These four aspects underline the essence of what Node.js is and encapsulate what powers it under the hood.

 

Let’s examine these keywords: 

Server-side

This simply indicates the capability to run it on servers.

Runtime

Upon reflection, it becomes apparent that Node.js essentially functions as an extension of a C++ application. Its core purpose is to facilitate the execution of JavaScript on the server side. However, the actual execution of this task is delegated to a distinct C++ library, which we will delve into later. Similarly, Node.js was conceived with notions of scalability and high performance in mind, attributes that are also attributed to a separate C library.

So, one might question the role of Node.js in this context. In essence, Node.js undertakes the responsibility of resource management and the establishment of connections between these resources. Furthermore, it furnishes developers with an API to harness these functionalities, permitting the utilization of these capabilities through the composition of JavaScript code.

non-blocking I/O model

Here emerges a key element of engagement: LIBUV. This C library shoulders the responsibility for the event-driven paradigm, boasting the renowned "event loop" alongside an array of other impressive features—such as HTTP, cryptography, file system operations, and more. However, delving into these specifics warrants a separate discussion.

Javascript

Here, at last, lies our primary objective: the additional C++ Library, V8. It takes the JavaScript code crafted by developers and converts it into machine code, which the computer's processor comprehends and executes.

Let's now delve deeper into V8 and its utilization within Node.js.

V8

Developed by Google and released to the open-source community in 2008, it serves as the foundation for executing JavaScript in Google Chrome and Node.js.

Let's create a hands-on illustration–something intriguing in which you can harness the power of V8 directly. To get started, installing it on macOS is as simple as executing the following command:

 > brew install v8

image4.png

Now that V8 is successfully installed on our system, we can leverage its capabilities through the V8 developer shell known as d8. To begin utilizing it, all you need to do is execute the following command:

 > d8

We are now able to begin executing JavaScript code, similar to how it's done with Node.js.

image1.png

V8 executes JavaScript code adhering to the ECMAScript specification. It primarily supports the elements exposed by ECMA, although it includes non-standard features. 

So, why not opt for using V8 directly on the server side, given that the initial goal was to run JavaScript on the server? Well, the reason is that it falls short in terms of capabilities. We require access to functionalities such as file system operations, executing HTTP requests, establishing database connections, and more. These essential features are made available through Node.js and its underlying library, libuv.

 

While it appears that we can't access additional features, there are exceptions. Let's examine two examples:

  • In Google Chrome, we can access the document (DOM), a capability not detailed in the ECMA specification.

image3.png

  • In Node.js, we can interact with the process, despite it not being covered by the ECMA specification.

image7.png

This reveals that these functionalities are made accessible through other resources, namely Web APIs and LIBUV or Nodejs, respectively.

So, how exactly does Node utilize V8?

Indeed, as mentioned earlier, Node.js is essentially another C++ application. Building on this understanding, we can simplify the explanation by utilizing pseudocode to abstract the core of the main Node.js process.

// The main Node.js process (fairly simple)
initialize v8


function runJavaScriptCode(code):
	v8.execute(code)
	
main(args) :
	userCode = readUserCodefromFile(args.path);
	runJavaScriptCode (userCode)

I understand that this might seem overly simplistic, but please keep in mind that we're just providing an illustrative example. We haven't delved into the complexities of libuv and the myriad of other components at play.

As Node.js initiates, it reads the user's code and subsequently employs this code to transmit it to V8 for execution (In a simplified version).

For those interested in delving deeper and linking the libuv library to gain a more comprehensive grasp of Node.js, let's take a look at a highly simplified representation to enhance our understanding.

// main node process pseudo code (fairly basic)
initialize v8
initilize libuv


function runJavaScriptCode(code):
	v8.execute(code)


function scheduleAsyncI0(task, callback):
	libuv.eventLoop.schedule(task, callback)


function startEventLoop():
	while(True):
		event = libuv.eventLoop.getNextEvent()
		if event
			runJavascriptCode(event.callback)
		if libuv.eventLoop.thereArePendingEvents)
			continue
		else
			break;


main(args):
	userCode = readUserCodeFromFile(args .path) ;
	runJavaScriptCode(userCode)

	startEventLoop()

Lastly, to emphasize this concept, let's examine a pseudocode representation of how Node.js manages asynchronous code execution and integrates it into the event loop.

Upon running a code snippet like this

image2.png

Behind the scenes, Node.js employs a mechanism akin to this

image6.png

Conclusions 

Through our exploration, we've come to understand that Node.js acts as a mediator between V8 and libuv, while also introducing its own set of functionalities. Armed with this knowledge, it becomes evident that the scope of V8 primarily involves executing code rooted in ECMAScript, while the array of additional capabilities finds their exposure through the combined efforts of Node.js and libuv.

References

https://www.figma.com/file/uzIhbxyRdf6ORkVTZTsIMy/Untitled?type=design&node-id=0-1&mode=design&t=qodFOeRgS7CGhGRW-0

https://cabulous.medium.com/how-v8-javascript-engine-works-5393832d80a7

https://v8.dev/docs/d8

Ready to be Unstoppable? Partner with Gorilla Logic, and you can be.

TALK TO OUR SALES TEAM