Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/lightpanda-io/zig-js-runtime
Add a JS runtime in your Zig project
https://github.com/lightpanda-io/zig-js-runtime
javascript-runtime v8 zig
Last synced: 3 months ago
JSON representation
Add a JS runtime in your Zig project
- Host: GitHub
- URL: https://github.com/lightpanda-io/zig-js-runtime
- Owner: lightpanda-io
- License: apache-2.0
- Created: 2022-09-15T15:48:29.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2024-05-22T12:31:06.000Z (6 months ago)
- Last Synced: 2024-05-22T13:37:15.824Z (6 months ago)
- Topics: javascript-runtime, v8, zig
- Language: Zig
- Homepage: https://lightpanda.io
- Size: 740 KB
- Stars: 4
- Watchers: 2
- Forks: 0
- Open Issues: 43
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# zig-js-runtime
A fast and easy library to add a Javascript runtime into your Zig project.
With this library you can:
- add Javascript as a scripting language for your Zig project (eg. plugin system, game scripting)
- build a web browser (this library as been developed for the [Ligthpanda headless browser](https://lightpanda.io))
- build a Javascript runtime (ie. a Node/Bun like)Features:
- [x] Setup and configure the Javascript engine
- [x] Expose Zig structs as Javascript functions and objects (at compile time)
- [x] Bi-directional "link" between Zig structs and Javascript objects
- [x] Support for inheritance (on Zig structs) and prototype chain (on Javascript objects)
- [x] Support for Javascript asynchronous code (I/O event loop)Currently only v8 is supported as a Javascript engine, but other engines might be added in the future.
This library is fully single-threaded to matches the nature of Javascript and avoid any cost of context switching for the Javascript engine.
## Rationale
Integrate a Javascript engine into a Zig project is not just embeding an external library and making language bindings.
You need to handle other stuffs:- the generation of your Zig structs as Javascript functions and objects (_ObjectTemplate_ and _FunctionTemplate_ in v8)
- the callbacks of Javascript actions into your Zig functions (constructors, getters, setters, methods)
- the memory management between the Javascript engine and your Zig code
- the I/O event loop to support asynchronous Javascript codeThis library takes care of all this, with no overhead thanks to Zig awesome compile time capabilities.
## Getting started
In your Zig project, let's say you have this basic struct that you want to expose in Javascript:
```zig
const Person = struct {
first_name: []u8,
last_name: []u8,
age: u32,// Constructor
// if there is no 'constructor' defined 'new Person()' will raise a TypeError in JS
pub fn constructor(first_name: []u8, last_name: []u8, age: u32) Person {
return .{
.first_name = first_name,
.last_name = last_name,
.age = age,
};
}// Getter, 'get_'
pub fn get_age(self: Person) u32 {
return self.age;
}// Setter, 'set_'
pub fn set_age(self: *Person, age: u32) void {
self.age = age;
}// Method, '_'
pub fn _lastName(self: Person) []u8 {
return self.last_name;
}
};
```You can generate the corresponding Javascript functions at comptime with:
```zig
const jsruntime = @import("jsruntime");
pub const Types = jsruntime.reflect(.{Person});
```And then use it in a Javascript script:
```javascript
// Creating a new instance of Person
let p = new Person('John', 'Doe', 40);// Getter
p.age; // => 40// Setter
p.age = 41;
p.age; // => 41// Method
p.lastName(); // => 'Doe'
```Let's add some inheritance (ie. prototype chain):
```zig
const User = struct {
proto: Person,
role: u8,pub const prototype = *Person;
pub fn constructor(first_name: []u8, last_name: []u8, age: u32, role: u8) User {
const proto = Person.constructor(first_name, last_name, age);
return .{ .proto = proto, .role = role };
}pub fn get_role(self: User) u8 {
return self.role;
}
};pub const Types = jsruntime.reflect(.{Person, User});
```And use it in a Javascript script:
```javascript
// Creating a new instance of User
let u = new User('Jane', 'Smith', 35, 1); // eg. 1 for admin// we can use the User getters/setters/methods
u.role; // => 1// but also the Person getters/setters/methods
u.age; // => 35
u.age = 36;
u.age; // => 36
u.lastName(); // => 'Smith'// checking the prototype chain
u instanceof User == true;
u instanceof Person == true;
User.prototype.__proto__ === Person.prototype;
```### Javascript shell
A Javascript shell is provided as an example in `src/main_shell.zig`.
```sh
$ make shellzig-js-runtime - Javascript Shell
exit with Ctrl+D or "exit">
```## Build
### Prerequisites
zig-js-runtime is written with [Zig](https://ziglang.org/) `0.13.0`. You have to
install it with the right version in order to build the project.To be able to build the v8 engine, you have to install some libs:
For Debian/Ubuntu based Linux:
```sh
sudo apt install xz-utils \
python3 ca-certificates git \
pkg-config libglib2.0-dev clang
```For MacOS, you only need Python 3.
### Install and build dependencies
The project uses git submodule for dependencies.
The `make install-submodule` will init and update the submodules in the `vendor/`
directory.```sh
make install-submodule
```### Build v8
The command `make install-v8-dev` uses `zig-v8` dependency to build v8 engine lib.
Be aware the build task is very long and cpu consuming.Build v8 engine for debug/dev version, it creates
`vendor/v8/$ARCH/debug/libc_v8.a` file.```sh
make install-v8-dev
```You should also build a release vesion of v8 with:
```sh
make install-v8
```### All in one build
You can run `make install` and `make install-dev` to install deps all in one.
## Development
Some Javascript features are not supported yet:
- [ ] [Promises](https://github.com/lightpanda-io/zig-js-runtime/issues/73) and [micro-tasks](https://github.com/lightpanda-io/zig-js-runtime/issues/56)
- [ ] Some Javascript types, including [Arrays](https://github.com/lightpanda-io/zig-js-runtime/issues/52)
- [ ] [Function overloading](https://github.com/lightpanda-io/zig-js-runtime/issues/54)
- [ ] [Types static methods](https://github.com/lightpanda-io/zig-js-runtime/issues/127)
- [ ] [Non-optional nullable types](https://github.com/lightpanda-io/zig-js-runtime/issues/72)### Test
You can test the zig-js-runtime library by running `make test`.
## Credits
- [zig-v8](https://github.com/fubark/zig-v8/) for v8 bindings and build
- [Tigerbeetle](https://github.com/tigerbeetledb/tigerbeetle/tree/main/src/io) for the IO loop based on _io\_uring_
- The v8 team for the [v8 Javascript engine](https://v8.dev/)
- The Zig team for [Zig](https://ziglang.org/)