{"id":30180948,"url":"https://github.com/streamich/jskernel","last_synced_at":"2025-08-12T08:06:29.712Z","repository":{"id":57284519,"uuid":"56888018","full_name":"streamich/jskernel","owner":"streamich","description":"Node.js exo-kernel dream - proposal","archived":false,"fork":false,"pushed_at":"2018-01-14T10:20:34.000Z","size":13010,"stargazers_count":49,"open_issues_count":3,"forks_count":8,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-08-09T09:12:27.660Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/streamich.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-04-22T22:10:22.000Z","updated_at":"2025-06-01T03:11:58.000Z","dependencies_parsed_at":"2022-09-17T02:11:48.413Z","dependency_job_id":null,"html_url":"https://github.com/streamich/jskernel","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/streamich/jskernel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamich%2Fjskernel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamich%2Fjskernel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamich%2Fjskernel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamich%2Fjskernel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/streamich","download_url":"https://codeload.github.com/streamich/jskernel/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamich%2Fjskernel/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269734044,"owners_count":24466545,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-10T02:00:08.965Z","response_time":71,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-12T08:06:13.568Z","updated_at":"2025-08-12T08:06:29.700Z","avatar_url":"https://github.com/streamich.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jskernel\r\n\r\n## Proposal\r\n\r\nThe Node.js exo-kernel dream: this is a proposal to create a JavaScript exo-kernel\r\nthat would have API compatible to Node.js but would be possible to run as part of the Linux kernel.\r\n\r\n\u003e Why do I need a JavaScript exo-kernel?\r\n\r\nWell, I don't know, but imagine you could have:\r\n\r\n 1. A complete OS image (not just a container, but including the kernel and Node.js) at less than 10Mb and it would boot in a couple of dozen milliseconds.\r\n 2. Full access to hardware from JavaScript.\r\n 3. Write hardware drivers in JavaScript.\r\n\r\nThere are already two projects ([NodeOS](https://node-os.com/) and [runtime.js](http://runtimejs.org/)) that work\r\ntowards creating a Node.js operating system, or kernel. See [architecture comparison](./docs/exokernels.md) for comparison\r\nwith `jskernel` proposal. The basic summary of the two is as follows:\r\n\r\n - `NodeOS` runs in *user space* on top of Node.js as the main process, so by default\r\n it comes with `npm` module ecosystem, however, it has no access to the *kernel space*.\r\n - `runtime.js` is compiled inside the kernel, so it has full access to the *kernel space*,\r\n however, it does not run on Node.js, not even `libuv` or `libc`, but just raw C++ bindings with kernel and V8,\r\n so one cannot run `npm` modules on runtime.js, unless they implement Node.js-like API.\r\n \r\nThe proposal of `jskernel` is to have the best of both worlds:\r\n\r\n\u003e Create a [Node.js standard library](https://github.com/nodejs/node/tree/master/lib) that would be able to run in *kernel space* (or *user space*).\r\n\r\nSo, here is how to achieve it:\r\n\r\n 1. Write everything in JavaScript (or TypeScript), no C/C++ bindings.\r\n 2. No dependencies, only the `syscall` function, syscalls executed directly from JavaScript.\r\n \r\nThis way we can re-create Node.js standard library whose only dependency will be the\r\n[system call function](https://en.wikipedia.org/wiki/System_call).\r\nWe would remove all native dependencies from Node.js, including Node.js itself, `libuv`, `libc` and even V8.\r\n\r\nThe only thing you would need to do to port this thing inside the Linux kernel or to a different JavaScript runtime would\r\nbe to port the `syscall` function, as it will be our only dependency.\r\n\r\nYou might think it is impossible and would take too much effort to rewrite `libc` and `libuv`,\r\nbut hey, we are coding in JavaScript, `libc` in JavaScript sounds like a little weekend project. Moreover, below is\r\na road map with some working prototypes, so its possible and it is actually simpler than it looks like because\r\nmany thing we can take straight from node's standard library. To make a first working prototype we just need to implement\r\nthe networking stack: `dgram`, `dns`, `net`, `http`.\r\n\r\nAlso, Node.js devs usually write their own database drivers and parsers in Node.js, instead \r\nof creating wrappers around the respective `C/C++` libraries, so, why do we execute system calls\r\nusing `libuv` and `libc`?\r\n\r\n## Roadmap\r\n\r\nBelow is a list of five packages from `libsys`, which simply provides the `syscall` function, to\r\n`unode`, which will be a Node.js compatible library whose only native dependency will be that `syscall` function.\r\n\r\n### `libsys`\r\n\r\n[`libsys`](http://www.npmjs.com/package/libsys) implements the basic `syscall` function, which will\r\nbe the only native dependency of the whole stack.\r\n\r\nHere is a simple example that prints `Hello world` in console:\r\n\r\n```js\r\nrequire('libsys').syscall(1, 1, new Buffer('Hello world\\n'), 12);\r\n```\r\n\r\nHere we basically execute No. `1` system call which is `SYS_write` to No. `1` file\r\ndescriptor which is `STDOUT`, so it goes to our consoles.\r\n\r\nDone, we have a `syscall` function, let's move further.\r\n\r\n### `libjs`\r\n\r\n[`libjs`](http://www.npmjs.com/package/libjs) will be like `libc` in C world: it will\r\nimplement wrappers around all the necessary system calls.\r\n\r\nFor example, reading a file synchronously:\r\n\r\n```js\r\nvar libjs = require('libjs');\r\n\r\nvar fd = libjs.open('/share/myfile.txt', libjs.FLAG.O_RDONLY);\r\nif(fd \u003e -1) {\r\n    var buf = new Buffer(1024);\r\n    var bytes_read = libjs.read(fd, buf);\r\n    console.log('Bytes read: ', bytes_read);\r\n    console.log(buf.toString().substr(0, bytes_read));\r\n    libjs.close(fd);\r\n} else {\r\n    console.log('Error: ', fd);\r\n}\r\n```\r\n\r\n### `libaio`\r\n\r\n[`libaio`](http://www.npmjs.com/package/libaio) will use `libjs` to implement *asynchronous* IO.\r\n\r\nHere is a prototype example from `libaio` of an asynchronous TCP socket that executes a simple `GET` request using `epoll` system calls:\r\n\r\n```js\r\nvar libaio = require('libaio');\r\n\r\nvar sock = new libaio.SocketTcp();\r\n\r\nsock.onconnect = () =\u003e {\r\n    console.log('Connected');\r\n    sock.write('GET /\\n\\n');\r\n};\r\n\r\nsock.ondata = (data) =\u003e {\r\n    console.log('Received:');\r\n    console.log(data);\r\n};\r\n\r\nsock.connect({host: '192.168.1.150', port: 80});\r\n```\r\n\r\n### `eloop`\r\n\r\n[`eloop`](http://www.npmjs.com/package/eloop) will implement worker pool to outsource\r\nCPU intensive operations that we cannot run asynchronously. Basically its task will\r\nbe similar to what `libuv` does for node.js -- provides a thread poll to run file IO and other CPU intensive tasks.\r\n\r\n### `unode`\r\n\r\n[`unode`](http://www.npmjs.com/package/unode) will integrate `eloop`, `libaio` and `libjs` to\r\nprovide a complete Node.js API, so that `npm` and all packages will run smoothly on `unode` without\r\neven knowing they are not actually running on node.js. It will be a simple drop-in replacement,\r\nwhere you run your apps with `unode` instead of `node`:\r\n\r\n    unode app.js\r\n\r\nMeanwhile, for time being `unode` will run on node.js patching already implemented functionality.\r\n\r\nHere is a list of modules from node's standard library that need to be implemented:\r\n\r\n*Copy-pasta:* The below modules we should be able to take from node's standard library\r\nand with little modification (or none at all) use in `unode`:\r\n\r\n    assert.js\r\n    console.js\r\n    events.js\r\n    path.js\r\n    process.js\r\n    punycode.js\r\n    querystring.js\r\n    readline.js\r\n    repl.js\r\n    module.js\r\n    url.js\r\n    util.js\r\n    stream.js\r\n    string_decoder.js\r\n        \r\n*Special:* When I said `syscall` function will be our only dependency, I actually lied. If you\r\nlook carefully at our system call function: it accepts numbers, strings, and `Buffer`s as arguments, where\r\nit uses `Buffer` as a pointer to a memory location of data. However, V8 has typed arrays and we will shim somehow the\r\n`Buffer` class function, there are already [buffer clones](https://github.com/feross/buffer) that work on typed arrays, we\r\njust need to make sure we can pass a pointer to the memory address of buffer's contents in our system calls:\r\n    \r\n    buffer.js\r\n    \r\n*Priority:* The below modules are priority ones for creating our first working prototype and get `npm` working.\r\nThey are perfectly doable using Linux's asynchronous sockets with `epoll` system calls:\r\n\r\n    dgram.js\r\n    dns.js\r\n    net.js    \r\n    http.js\r\n    \r\n*File system:* `fs` is not an immediate priority because of two reasons: (1) there is no good async way on Linux\r\nto handle files, you have to resort to threads; (2) we don't really need a file system in our first prototype,\r\ninstead we can use an in-memory file system like [memfs](https://github.com/streamich/memfs):\r\n\r\n    fs.js\r\n    \r\n*Misc:* These are some not-important or node.js and V8 specific modules:\r\n    \r\n    vm.js\r\n    v8.js\r\n    os.js\r\n    tty.js\r\n    timers.js\r\n\r\n*Hard ones:* And finally we get to the modules that are hard to implement in pure JavaScript. These are\r\ncomputationally intensive modules for which we would need a worker pool to run in background:\r\n    \r\n    child_process.js\r\n    cluster.js   \r\n    crypto.js\r\n    domain.js\r\n    https.js\r\n    tls.js\r\n    zlib.js\r\n\r\nAnd even these *\"hard ones\"* are not that hard, because pure JavaScript implementations\r\nalready exist, we just need to solve the background worker pool problem:\r\n    \r\n - [`forge`](https://github.com/digitalbazaar/forge) is JavaScript implementation of `tls.js`\r\n - [`pako`](https://github.com/nodeca/pako) is JavaScript implementation of `zlib.js`\r\n    \r\n\r\n## Moving Inside the Kernel\r\n\r\nImagine that we have `unode` complete with the whole node's API. Remember\r\nthat now our whole stack has only one dependency -- the `syscall` function -- we have \r\nremoved all C/C++ dependecies. This, means that to port all of that to a different\r\nJS runtime or into the Linux kernel is as simple as porting the `syscall` function.\r\n\r\nFinally, once inside the kernel we can expose more of the kernel's functionality\r\nto JavaScript.\r\n\r\n## Development\r\n\r\n    git clone https://github.com/streamich/jskernel\r\n\r\nIf you don't have Docker:\r\n\r\n    vagrant up\r\n    vagrant ssh\r\n    sudo /share/install.sh\r\n    \r\nStart a Docker container:\r\n    \r\n    docker build -t jskernel .\r\n    docker run -it -v ~/dev/jskernel:/share --name myjskernel jskernel /bin/bash\r\n    cd /share\r\n    npm install -g npm@latest\r\n    npm install -g node-gyp n typescript tsd mocha\r\n    \r\nNext time just do:\r\n\r\n    docker start myjskernel\r\n    docker exec -it myjskernel bash\r\n    \r\n\r\n## Repository Contents\r\n\r\n - `libsys` -- syscall function module for Node.js.\r\n - `static-buffer` -- `StaticBuffer` and `StaticArrayBuffer` implementations.\r\n - `typebase` -- basic *struct* reader/writer into/from `Buffer`.\r\n - `libjs` -- syscall wrapper.\r\n - `fslib` -- `require('fs')` implementation.\r\n - `libaio` -- Wrapper around asynchronous system calls.\r\n - `ass-js` -- Assembler.js, x86 assembler.\r\n - `cpuid` -- basic utility to work with `cpuid` system call from JavaScript.\r\n - `elf` -- ELF file reader/writer.\r\n - `f1` -- JavaScript runtime written in JavaScript that compiles JavaScript to machine code.\r\n - `full-js` -- Drop-in Node.js replacement, written in pure JavaScript.\r\n - `jsc` -- Write C in JavaScript and JIT compile.\r\n    \r\n    \r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstreamich%2Fjskernel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstreamich%2Fjskernel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstreamich%2Fjskernel/lists"}