Crossing the JS/C++ Boundary
Tags: node, javascript
Published: 2019-10-15 13:55:33

This article was originally posted on Medium as an extension to my article series on NodeJS Event Loop on Medium:

{% medium https://blog.insiderattack.net/crossing-the-js-c-boundary-advanced-nodejs-internals-part-1-cb52957758d8 %}

In NodeJS Event Loop article series, I explained,

*   [Event Loop and the Big Picture](https://blog.insiderattack.net/event-loop-and-the-big-picture-nodejs-event-loop-part-1-1cb67a182810)
*   [Timers, Immediates and Next Ticks](https://blog.insiderattack.net/timers-immediates-and-process-nexttick-nodejs-event-loop-part-2-2c53fd511bb3)
*   [Promises, Next-Ticks, and Immediates](https://blog.insiderattack.net/promises-next-ticks-and-immediates-nodejs-event-loop-part-3-9226cbe7a6aa)
*   [Handling I/O](/handling-io-nodejs-event-loop-part-4-418062f917d1)
*   [Event Loop Best Practices](https://blog.insiderattack.net/event-loop-best-practices-nodejs-event-loop-part-5-e29b2b50bfe2)
*   [New changes to timers and microtasks in Node v11](https://blog.insiderattack.net/new-changes-to-timers-and-microtasks-from-node-v11-0-0-and-above-68d112743eb3)

In this article, I’m going to explain how NodeJS internally glue a bunch of `C`/`C++` and JavaScript pieces all together to build an amazing server-side Javascript framework.

> **For you to clearly understand how it works, I have included few code snippets in this post from the NodeJS codebase. Please note that I have truncated certain parts of those for brevity and have added some comments and log lines myself. Also, I would like you to understand that NodeJS codebase is very active and is subject to frequent code refactoring. Therefore, these code snippets might be drastically different across revisions. However, the overall functionality will be almost similar. Although these snippets would be gone in future releases, understanding how they work right now could make it really easy for you to understand the entire NodeJS codebase.**

[In the Event Loop series](https://blog.insiderattack.net/event-loop-and-the-big-picture-nodejs-event-loop-part-1-1cb67a182810), I explained to you how it works, different phases of it and the sequence. But the event loop is implemented in [libuv](https://libuv.org/) and nowhere in its code is mentioned about `process.nextTick`. Now the weird question is….Where is `process.nextTick` callbacks are called? The only thing we know is that they are called at the start and between each phase of the event loop.

> I presume you have a sound understanding of the different phases of the event loop, microtasks, `process.nextTick` and other terminology related to Node. If you haven’t I do appreciate if you can read the aforementioned Event Loop article series before reading this article as you might feel it difficult to follow some of the concepts mentioned here.

First of all, let’s see how `process.nextTick` is defined in JavaScript context so that we can call it. To come to that, let’s see how NodeJS starts up.

## Initialization: Starting V8 Environment

During the initialization of NodeJS runtime, an instance of `V8` environment is created and the environment is started by calling `Environment::Start` method. In this method, `SetupProcessObject` is executed which makes some interesting `C++` functions accessible from JavaScript.

{% gist https://gist.github.com/deepal/1f9fa2d399f9ff8914329f44abc7912b %}

{% gist https://gist.github.com/deepal/a5a27d4daabd759396b6af11cf35fc1f %}

As you can see `_setupNextTick` function is set in the `process` object during the initialization of `V8` environment. `_setupNextTick` is a reference to the `SetupNextTick` function in `C++` context. Following is the definition of the `SetupNextTick` function.

{% gist https://gist.github.com/deepal/3038aa5229ae42d5ff3d0af6f216248d %}

I will explain how this `SetupNextTick` function comes into play in a while.

## Loading Bootstrappers

After initializing `V8` environment, two JS scripts called `bootstrappers` are run.

They are,

**Loaders Bootstrapper**: `internal/bootstrap/loaders.js`

**Node Bootstrapper**: `internal/bootstrap/node.js`

Node bootstrapper calls its `startup` function during execution.

{% gist https://gist.github.com/deepal/cc606b9979c0e36de1f4363bb35fa36e %}

During the execution of `startup()` function, NodeJS `require`s the next tick module from `internal/process/next_tick` and executes its `setup()` export function.

This `setup()` function is exported from `next_tick.js` and is a reference to the function `setupNextTick` defined in the same file.

{% gist https://gist.github.com/deepal/7ced17ae17d7a7faf74dc2717b3e9d4e %}

*   Upon calling, `setupNextTick` function sets the attribute `nextTick` in the `process` object (line 22) as a reference to the `nextTick` function defined in the same scope. This is how `process.nextTick` can be called from userland.
*   `nextTick` function (line 37) merely adds a given callback into a queue.
*   There’s another function called `_tickCallback` (line 27) defined in the same scope which is where the `nextTick` queue is processed. For ease of reading, I extracted it out as a separate gist as follows. Let’s read it carefully.

{% gist https://gist.github.com/deepal/c06eefb53b0e3a380a340953c2c8fd09 %}

1.  Once `_tickCallback()` function is called, it will iterate through the queue where `nextTick` callbacks are queued and will execute each and every callback until there are no callbacks left in the queue (line 4, inner `while` loop).
2.  Then, the `_tickCallback()` function will call `runMicrotasks()` function (line 21). **This function will process the microtasks queue (e.g, callbacks of resolved/rejected promises)**. It’s possible that new `nextTick` callbacks are added while executing microtasks (e.g, call of `process.nextTick` in promise resolve/reject callback).
3.  Above step1 and step2 is repeated until no more callbacks left in the `nextTick` queue (line 3, outer `do-while` loop)

**The golden point is….. You need to trigger** `**_tickCallback**` **JavaScript function somehow during two phases of the event loop in order to process the** `**nextTick**` **queue and the microtasks queue.**

To do this, `_tickCallback` function should be passed somehow to `C++` context.

## Binding JS function to C++

`_tickCallback` function is referenced in `C++` context by calling `process._setupNextTick` inside `setupNextTick`. Upon the execution of `process._setupNextTick`, it’s passed `tickCallback` as the only parameter (see the `next_tick.js` gist above).

Now if you remember I explain before, `process._setupNextTick` is actually a `C++` function which is referred in JavaScript context upon the initialization of `V8` environment. For clarity, I’ll just copy/paste the gist again (It’s time to scroll up if you don’t remember ;))

{% gist https://gist.github.com/deepal/a5a27d4daabd759396b6af11cf35fc1f %}

The equivalent `C++` function to `process._setupNextTick` JS function is `SetupNextTick` which is defined in `node.cc`.

{% gist https://gist.github.com/deepal/3038aa5229ae42d5ff3d0af6f216248d %}

This method will call `set_tick_callback_function` with the first parameter provided. Therefore, whatever you pass as the first parameter to `process._setupNextTick` is passed to `set_tick_callback_function`. Now go up and check what we call `process._setupNextTick` within `setupNextTick` JS definition.

{% gist https://gist.github.com/deepal/e2e9252b609410ea71e92405a5805f2e %}

Wow!! Eventually, the reference to `_tickCallback` function is passed to `set_tick_callback_function` in `C++`. `set_tick_callback_function` will set the reference to the `_tickCallback` function as `tick_callback_function` in the `V8` environment. The conclusion is, calling `tick_callback_function` in `V8` environment triggers the execution of JavaScript `_tickCallback` function which subsequently processes the `nextTick` queue and the microtask queue.

<noscript><img alt="" class="gk n o gj af" src="https://miro.medium.com/max/1872/1*ffpBLArUfdX8BTkXed1dsw.png" width="936" height="636" role="presentation"/></noscript>

Now if you recall what I mentioned above….

> **The golden point is….. You need to trigger** `**_tickCallback**` **JavaScript function somehow during two phases of the event loop in order to process the** `**nextTick**` **queue and the microtasks queue.**

You know how ;)

Now we need to know where `tick_callback_function` is called in `C++` context. Let’s go back to the event loop now.

## Crossing the boundary

In NodeJS, we write all our code in Javascript, which means all of our callbacks are JavaScript. So how are they triggered by `C`? The answer is, this binding glue is the `C++` bindings for libuv. Those are the functions written in `C++` who bridges `C++` and JavaScript and invoke JavaScript functions when libuv asks them to. Let’s try to understand it in a clear way by an example.

When you are adding multiple timers using `setTimeout`, they all will be grouped together by their timeout value so that timers with the same timeout value will be in a single list. And Javascript will provide a callback function `processTimers` with each list to execute its callbacks. This callback function will be passed from JavaScript to `C++` as `OnTimeout` in `C++`, and then `C++` to libuv(`C`) as `timer_cb` attached to a handle which is invoked by libuv. Essentially, calling the `timer_cb` of a handle in libuv will trigger the execution of the multiple timers which were set at the same time with the same timeout value (I know you have questions now, but just keep them in mind for my next post on NodeJS timers in detail ;))

<noscript><img alt="" class="gk n o gj af" src="https://miro.medium.com/max/302/1*RYhG0Un7j4hBzTZ39PLn5Q.jpeg" width="151" height="321" role="presentation"/></noscript>

How a processTimers() JavaScript function is triggered from libuv

When `OnTimeout` function in `C++` is called, NodeJS will cross the `C++` boundary all the way to JavaScript and will execute the given JavaScript callback. When it crosses the `C++`/`JS` Boundary, an interesting function is called named `MakeCallback`.

Now if you search for `MakeCallback`, you will find multiple overloaded `MakeCallback` functions in `node.cc` and `async_wrap.cc` with different signatures:

At the time of this writing:

{% gist https://gist.github.com/deepal/66e9b160b24942e6c74895bd4f714369 %}

Each of them is written for very distinct purpose but if you look closely, you’ll see that they all eventually calls the `InternalMakeCallback` function defined in `node.cc`.

{% gist https://gist.github.com/deepal/b7303f5a865dde254a6df626e78b6d79 %}

When `MakeCallback` is called, it will pass the appropriate JS callback which needs to be called by the `InternalMakeCallback` as the 3rd parameter (`callback`) of the `InternalMakeCallback`.

**This** `**callback**` **is the almighty who processes a single phase of the event loop.**

Then comes the most important part. You’ll see that after calling the provided `callback`, `scope.Close()` function is called.

Let’s look at the definition of `scope.Close()` function defined in `node.cc`.

{% gist https://gist.github.com/deepal/7ef5368a9da1c777d53a6ab65664633d %}

Within this function, it executes the `tick_callback_function` in `V8` environment.

Do you remember what `tick_callback_function` is? It’s the same `_tickCallback` JavaScript function which is referred in the `C++` context which indicates that every time `InternalMakeCallback` is called from `C++` `_tickCallback` function is called at the end. Therefore, at the end of each phase, `nextTick` queue and the microtask queue are processed.

But, If you read my Event Loop article series or if you have personally experienced `process.nextTick` callbacks and the microtasks are run even before the timers phase start. How is this happen?

This is because the **Node Bootstrapper** which I mentioned above also loads the CommonJS module loader internally. During the bootstrap of CommonJS module loader, it manually triggers `_tickCallback` to process any `nextTick` callbacks added at the start.

{% gist https://gist.github.com/deepal/400b2a9fdd8088a54bb586a51df125f2 %}

**PS: For the above examples, I referred to the NodeJS source at revision** [**b267d2aae6**](https://github.com/nodejs/node/tree/b267d2aae6fc598ae0dd2d6134ec95ddd09891ba)**. Due to many refactoring processes, the above example codes might be different across different NodeJS versions.**

I suppose you now know how the mysterious `process.nextTick` works. If you have any questions regarding anything I’ve mentioned or if you like to add something please feel free to comment. Thanks.

_Background Image Courtesy: [https://www.hdwallpapers.in/walls/earth_horizon-wide.jpg](https://www.hdwallpapers.in/walls/earth_horizon-wide.jpg)_