Small and modular JavaScript runtime for desktop and mobile
Small and modular JavaScript runtime for desktop and mobile
Small and modular JavaScript runtime for desktop and mobile. Like Node.js, it provides an asynchronous, event-driven architecture for writing applications in the lingua franca of modern software. Unlike Node.js, it makes embedding and cross-device support core use cases, aiming to run just as well on your phone as on your laptop. The result is a runtime ideal for networked, peer-to-peer applications that can run on a wide selection of hardware.
npm i -g bare…The specified or is run using Module.load(). For more information on the module system and the supported formats, see .
Bare is built on top of , which provides low-level bindings to V8 in an engine independent manner, and , which provides an asynchronous I/O event loop. Bare itself only adds a few missing pieces on top to support a wider ecosystem of modules:
SharedArrayBuffer support.Everything else if left to userland modules to implement using these primitives, keeping the runtime itself succinct and bare. By abstracting over both the underlying JavaScript engine using libjs and platform I/O operations using libuv, Bare allows module authors to implement native addons that can run on any JavaScript engine that implements the libjs ABI and any system that libuv supports.
Bare is designed to be embedded alongside code the embedder may not fully trust, and Bare.Addon.seal() is the mechanism for freezing the set of native code a process may load. What that does and does not promise is written down in docs/threat-model.md, which embedders should read before running untrusted JavaScript.
BareThe core JavaScript API of Bare is available through the global Bare namespace.
Bare.platformThe identifier of the operating system for which Bare was compiled. The possible values are android, darwin, ios, linux, and win32.
Bare.archThe identifier of the processor architecture for which Bare was compiled. The possible values are arm, arm64, ia32, mips, mipsel, riscv64, and x64.
Bare.argvThe command line arguments passed to the process when launched.
Bare.pidThe ID of the current process.
Bare.exitCodeThe code that will be returned once the process exits. If the process is exited using Bare.exit() without specifying a code, Bare.exitCode is used.
Bare.versionThe Bare version string.
Bare.versionsAn object containing the version strings of Bare and its dependencies.
Bare.exit([code])Immediately terminate the process or current thread with an exit status of code which defaults to Bare.exitCode.
Bare.suspend([linger])Suspend the process and all threads. This will emit a suspend event signalling that all work should stop immediately. When all work has stopped and the process would otherwise exit, an idle event will be emitted. If the process is not resumed from an idle event listener, the loop will block until the process is resumed.
Bare.wakeup([deadline])Wake the process and all threads during suspension. This will emit a wakeup event signalling that work may be performed until deadline is reached.
Bare.idle()Immediately suspend the event loop and trigger the idle event.
Bare.resume()Resume the process and all threads after suspension. This can be used to cancel suspension after the suspend event has been emitted and up until all idle event listeners have run.
Bare.on('uncaughtException', err)Emitted when a JavaScript exception is thrown within an execution context without being caught by any exception handlers within that execution context. By default, uncaught exceptions are printed to stderr and the processes aborted. Adding an event listener for the uncaughtException event overrides the default behavior.
Bare.on('unhandledRejection', reason, promise)Emitted when a JavaScript promise is rejected within an execution context without that rejection being handled within that execution context. By default, unhandled rejections are printed to stderr and the process aborted. Adding an event listener for the unhandledRejection event overrides the default behavior.
Bare.on('beforeExit', code)Emitted when the loop runs out of work and before the process or current thread exits. This provides a chance to schedule additional work and keep the process from exiting. If additional work is scheduled, beforeExit will be emitted again once the loop runs out of work.
If the process is exited explicitly, such as by calling Bare.exit() or as the result of an uncaught exception, the beforeExit event will not be emitted.
Bare.on('exit', code)Emitted when the process or current thread exits. If the process is forcefully terminated from an exit event listener, the remaining listeners will not run.
[!CAUTION]
Additional work MUST NOT be scheduled from anexitevent listener.
Bare.on('suspend', linger)Emitted when the process or current thread is suspended. Any in-progress or outstanding work, such as network activity or file system access, should be deferred, cancelled, or paused when the suspend event is emitted and no additional work should be scheduled. A suspend event listener may call Bare.resume() to cancel the suspension.
Bare.on('wakeup', deadline)Emitted when the process or current thread wakes up during suspension. Once the process becomes idle, or if the process is not idle by the time deadline has passed, the process will suspend itself again and an idle event be emitted. A wakeup event listener may call Bare.resume() to resume the process.
Bare.on('idle')Emitted when the process or current thread becomes idle after suspension. After all handlers have run, the event loop will block and no additional work be performed until the process is resumed. An idle event listener may call Bare.resume() to cancel the suspension.
Bare.on('resume')Emitted when the process or current thread resumes after suspension. Deferred and paused work should be continued when the resume event is emitted and new work may again be scheduled.
…Bare.AddonThe Bare.Addon namespace provides support for loading native addons, which are typically written in C/C++ and distributed as shared libraries.
[!NOTE]
This is an advanced API that users should never have to interact with directly.
Addon.hostThe target triplet identifying the current addon host.
Addon.sealedWhether addon loading has been sealed with Addon.seal().
Addon.seal()Seal addon loading. Once sealed, no further dynamic addons can be loaded by the current thread or any other thread of the process, now or in the future; attempting to do so throws. Statically linked addons are compiled in and remain available.
This is a one-way operation that cannot be undone for the lifetime of the process. It is intended for embedders that wish to load a fixed set of trusted addons up front and then prevent any further native code from being introduced, such as when establishing a sandbox.
The seal applies to the process alone. Embedders running several Bare processes within the same operating system process may seal each of them independently, and sealing one has no effect on the addons the others may load. Addons are likewise owned by the process that loaded them and are unloaded when it is torn down.
Sealing also freezes the context registry that embedders publish handles to, after which nothing further may be published to it.
For what sealing guarantees, what it deliberately leaves alone, and what embedders are expected to do on top of it, see docs/threat-model.md.
const addon = new Addon(url)Load a static or dynamic native addon identified by url. If url is not a static native addon, Bare will instead look for a matching dynamic object library.
addon.urlThe WHATWG URL identifier of the addon.
addon.exportsThe exports of the addon.
Bare.ThreadThe Bare.Thread namespace provides support for lightweight threads. Threads are similar to workers in Node.js, but provide only minimal API surface for creating and joining threads.
[!NOTE]
This is an advanced API that users should never have to interact with directly.
Thread.isMainThreadtrue if the current thread is the main thread.
Thread.selfA reference to the current thread as a ThreadProxy object. Will be null on the main thread.
Thread.self.dataThe data that was passed to the current thread on creation. Will be null if no data was passed.
const thread = new Thread([filename[, source]][, options][, callback])Start a new thread that will run source, which is a string or a Buffer. If callback is provided, its function body will be used as the source instead and invoked on the new thread with Thread.self.data passed as an argument.
A thread is loaded through a protocol that reaches nothing, so it runs the source it was given and no more; filename names that source rather than locating it. Anything else the thread needs, including the modules it imports, must travel with it as source or data. To run a module graph on a thread, gather it into a first and pass the bundle as source, which is what does.
[!IMPORTANT]
A thread does not inherit the module protocol of whoever spawned it. Reading a graph off disk and handing it over is the spawner's job, so that a thread never reaches further than the code that started it.
Options include:
{
// Optional data to pass to the thread
data: null,
// Optional transfer list
transfer: [],
// Optional source encoding if `source` is a string
encoding: 'utf8',
// Optional stack size in bytes, pass 0 for default
stackSize: 0
}thread.joinedWhether or not the thread has been joined with the current thread.
thread.join()Block and wait for the thread to exit.
thread.suspend([linger])Suspend the thread. Equivalent to calling Bare.suspend() from within the thread.
thread.wakeup([deadline])Wake the thread. Equivalent to calling Bare.wakeup() from within the thread.
thread.resume()Resume the thread. Equivalent to calling Bare.resume() from within the thread.
thread.terminate()Terminate the thread. Equivalent to calling Bare.exit() from within the thread.
Bare.IPCThe Bare.IPC namespace provides support for optional streaming communication between an embedder and JavaScript code. By default, its value is null indicating that streaming communication is not supported. If set by embedders, Bare.IPC is expected to be an instance of a Duplex stream.
[!NOTE]
This is an advanced API that users should never have to interact with directly.
Bare can easily be embedded using the C API defined in include/bare.h:
#include
#include
bare_t *bare;
bare_setup(uv_default_loop(), platform, &env /* Optional */, argc, argv, options, &bare);
bare_load(bare, filename, source, &module /* Optional */);
bare_run(bare, UV_RUN_DEFAULT);
int exit_code;
bare_teardown(bare, UV_RUN_DEFAULT, &exit_code);If source is NULL, the contents of filename will instead be read at runtime. For examples of how to embed Bare on mobile platforms, see and .
Addons sometimes need a handle that only the embedder can produce, such as a JavaVM * on Android. As an addon is only ever passed a JavaScript environment and its exports, it
No open issues yet, or sync has not completed.