Home > Web Front-end > JS Tutorial > Creating a Runtime

Creating a Runtime

Linda Hamilton
Release: 2024-10-27 09:55:03
Original
974 people have browsed it

Criando uma Runtime

Hello, my name is Lucas Wasilewski and just like I put in the project description on my github since I started programming with NodeJS (at the beginning of 2021) I've always wanted to write something that looked like the tool, this only increased after I watched the documentary about the project and I was amazed at how the open source world can have several twists and turns and be very welcoming when it wants to. And after a week of a lot of head-scratching, I decided to write this article so that future crazy programmers who want this challenge don't make the same mistakes I did.

Javascript Runtimes

This term can easily mislead anyone who doesn't understand much about the subject and so a good definition is needed:

A Javascript runtime is a tool that allows you to run the language outside the browser

Nowadays there are 3 popular runtimes: NodeJS, Deno (Node Killer) and Bun (Deno Killer), but they basically do the same thing: they allow you to use javascript away from the browser and use other libraries to create features new ones, and that's very good, since you can use any of them to build a server, create libraries and even mobile or terminal applications.

Both Node and Deno were created by the same person: Ryan Dahl, and back in 2009 he created the tool to enable developers to create "async IO" applications, that is, that did not block the main thread but still continued to respond to requests, with this in mind he created Libuv, a library that does just that. Until then the project was just a big pile of C and if he wanted more people to use the tool he needed some language that was easier to understand and use, coincidentally, at the same time Google launched V8, which in general is a ultra-fast javascript compiler, this made him combine the two and thus create Node.

Some time later (9 years more specifically), Ryan left the project and went to work on other things that he considered more interesting, this made him realize several errors that could be fixed in Node, but the community was already very large and having to take a big step back was impossible, so, determined to do a better job, he creates Deno, another IO runtime that promises to be much superior to Node, as of today (2024) Deno is in version 2.0 and is very stable for projects and the community.

This whole story made more people join the runtime community and this also led us to the creation of Bun, and much better, mine and your runtime! Now let's get down to business.

Compiling V8

As previously stated, V8 is the Node engine, so we will have to actually download it and compile it manually to have access to its libraries and headers. As it is a Google project, they have their own methods for downloading and compiling, so for this we will have to follow their manual: link, just copying and pasting will take you to the final commands.

However, here I made a mistake that took 3 days for me to realize that I was doing everything wrong. After generating the build configuration files with:

tools/dev/v8gen.py x64.release
Copy after login
Copy after login

You need to be very careful with the args.gn file inside the out.gn/x64.release/ folder because it contains the build configuration that the ninja (compilation tool) will use to generate the library files, some Old tutorials use the v8_monolithic = true parameter, but in recent versions this is no longer used. According to this StackOverflow comment, we now need to use the is_component_build = true parameter to generate the right files and modify the flags when compiling the file, something very silly that if you don't pay attention to can waste precious time.

After placing the rest of the flags correctly, we just need to run the command to compile the project

ninja -C out.gn/x64.release

In the meantime, go eat something, because V8 is a very extensive project with countless tests, depending on your machine this process can easily take 1 hour or more, so leave it running and continue reading.

Where is console.log?

After compiling you can take a look at v8/samples/hello-world.cc and start to get an idea of ​​how to compile javascript, but specifically these lines:

v8::Local<v8::String> source =
          v8::String::NewFromUtf8Literal(isolate, "'Hello' + ', World!'");

// Compile the source code.
v8::Local<v8::Script> script =
          v8::Script::Compile(context, source).ToLocalChecked();
Copy after login
Copy after login

Go ahead and play with the string that contains "Hello World", create functions, loops, conditionals and go crazy when you realize that if you include the classic console.log() you will receive an undefined, that firstly it perplexed me, I always thought that the console object was part of V8 itself, but in fact Node itself includes it and browsers include it as part of the DOM (post from 2012 saying that console.log is probably not supported by browsers), meaning we'll have to create it ourselves.

Hello World!

To be able to create our own functions, we first need to understand that V8 works with several scopes, one of them is context, where it is through this that the runtime knows where and how to execute the script individually, within it there may be a global object that is shared among all the others, and it is within it that we will insert our custom functions.

tools/dev/v8gen.py x64.release
Copy after login
Copy after login

With these lines we were able to create an object called global, we inserted a "print" function template that when executed calls the Print function.

v8::Local<v8::String> source =
          v8::String::NewFromUtf8Literal(isolate, "'Hello' + ', World!'");

// Compile the source code.
v8::Local<v8::Script> script =
          v8::Script::Compile(context, source).ToLocalChecked();
Copy after login
Copy after login

The Print function receives this crazy parameter that contains information about the function call within javascript and it is through it that we iterate over all the items within it, transform them into a C string and print them on the screen, very direct, very simple and it fulfills its role, that's enough to put it in a file, read it and play it on the V8 (I leave that one in your hands).

v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(GetIsolate());
global->Set(GetIsolate(), "print", v8::FunctionTemplate::New(GetIsolate(), this->Print));
v8::Local<v8::Context> context = v8::Context::New(GetIsolate(), nullptr, global);
Copy after login

Libuv

Well, I hope that by now you've been able to follow along and have even stopped reading to make some unique implementations for your homemade Node, but V8 will only take us so far, so that we can get closer to a professional runtime we need to make javascript able to perform more operations, to do this we will use Libuv, which was created precisely for this.

You can find the tutorial to install and compile here. The important thing to note here is that it gives us the freedom to do asynchronous operations, that is, without blocking the main thread, thus allowing the program to continue executing while doing heavier work (like opening a file or waiting for requests in a server socket).

It itself is already built-in with the functionality to create an http server, so we just need to synchronize it with the V8 calls. Make no mistake, this is not an easy task, because the interface of the two libraries differs a lot so it is difficult to connect both, but there is always a way and the node source code is open so make sure to steal some ideas from there

Conclusions

We have reached the end of another article and with it we look at some details that I noticed during the implementation. The first is definitely the complexity, of course, it's not a simple project, but once you understand how to interact with the V8 interface things go very quickly.

This project made me understand Node much better too. The fact that the runtime is just a conglomerate of libraries communicating makes it very easy to understand how more complex things (like the "event-loop") work.

If you want to see what I did right, or probably very wrong, please take a look at the project on github: done

Talk is cheap, show me the code - Linus Torvalds

## References

https://github.com/libuv/libuv
https://v8.dev/docs
https://stackoverflow.com/questions/71213580/cant-get-v8-monolith-to-genorate
https://github.com/ErickWendel/myownnode
https://github.com/WasixXD/done

The above is the detailed content of Creating a Runtime. For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template