Under the call site's hood
In the following, we'll use the readFileSync
and readFile
to illustrate the underlying principles.
TypeScript call site
In Deno, we can read files like this:
The above code is very simple and straightforward, but how does Typescript read the file actually? And in the absence of libuv
, how does Deno implement asynchronous calls?
In fact, the Deno APIs that need to use system calls are converted to messaging process like the following:
Both the sendSync
and sendAsync
methods call the libdeno.send
method on the underlying, and this method is a C++ binding function injected by V8. After this processing, the function call information is passed to C++.
In addition to dispatching messages, TypeScript end also needs to register a callback function to get the asynchronous result sent back from the Rust side:
libdeno.recv
is also a binding function injected in V8 to register callback for receiving messages. For details on this function, please refer to the next section.
Let's take a look at how C++ consumes received messages.
C++ converter
Note: The following is pseudo libdeno.send
code, just for the sake of easy understanding, the actual code is not like this.
The Send
function get args and invoke the recv_cb_
. Notice that the recv_cb_
is defined in the Rust code.
The return value of the libdeno.send
will be set by deno_respond
:
The deno_respond
is called by the recv_cb_
and will be distinguished between synchronous and asynchronous when executed. When the call is synchronous, deno_respond
returns the result directly. And when the call is asynchronously, the function is triggered asynchronously and calls the callback function defined in TypeScript.
Rust executor
The journey of the function call comes to the last station. The Rust code maps the type of function call to the corresponding handler and handles synchronous and asynchronous calls based on event-loop. For details on event-loop, see the next section.
Last updated