Open groundwater opened 10 years ago
Sometimes I imagine you will want to boot a new context, and other times you will want a new isolate. It remains to be seen how isolates and contexts will be used to construct a system, but we definitely want both constructs as first-class runtimejs functionality.
Agreed. Isolates are useful if user wants to have separate heap and GC for some drivers/applications. I'm working on preemption problem though. Hopefully, I will be able to implement it for contexts on the same isolate.
I think we should drop files as a first-class concept, rather "everything is a module"
Ok. My proposal: I think we should not use module system for resource management. Instead we can use program arguments object to pass everything program needs.
This is the user program example https://github.com/runtimejs/runtime/blob/master/initrd/app/example.js
runtime.args()
to get it's arguments.{
"system" : <system resources>,
"env" : <environment>,
"data": <program data like command line etc>
}
args.system.process.spawn( path, options, data, env )
example (start /random.js
using current process environment args.env
)
args.system.process.spawn('/random.js', {}, {
command: '-a -b -c=value'
}, args.env);
Thoughts?
I don't think we should be bound by the abstractions governing most *nix systems. Specifically the "everything is a file" abstraction, and the process abstraction.
isolates and contexts
Instead of a processes, we have isolates and contexts, since these already exist in v8. Each has features and constraints, and we should probably just embrace them as-is.
Sometimes I imagine you will want to boot a new context, and other times you will want a new isolate. It remains to be seen how isolates and contexts will be used to construct a system, but we definitely want both constructs as first-class runtimejs functionality.
modules
I think we should drop files as a first-class concept, rather "everything is a module".
By default, JavaScript code running in v8 has no external access. It cannot access the file system, the network, or make system calls. External access should be passed in via the ES6 module feature.
You gain access to external objects via the ES6 import syntax, e.g.
This is very similar to how an executable on linux links against libc headers during compilation, e.g.
In most implementations, the actual IO code is not contained in the executable file on disk, but the shared library loaded at runtime.
We take this idea to its completion in runtime, where every parent process has full control over what gets passed into a child process. Each parent defines the moduel loader for its child. A parent can re-export its own imports, export a subset, or even provide a new API to its child.
Moule linking occurs during compile not run. If a child attempts to import a disallowed or missing module, it will receive an error during the compile step.
libraries
The first context that runs has its module loader defined by the kernel. At this point there is no file system, so the module loader cannot load files from disk, only memory.
The kernel should provide raw device and memory access.
User code does not want to deal with raw devices but files; kernel modules should import raw device access from the kernel, but export a file-system api.
Children spawned by the kernel module will be handed a working file system implementation.
user space
There is no longer just a kernel space and user space. Contexts run with imports defined by their parent context. A parent may decide to pass privileged functions to their children, provide proxies, or disallow the import altogether.
summary
At the core of runtime, we only need a module system. The kernel must provide the initial module loader, but from then on all subsequent loaders are defined by other modules.