Skip to main content

Crate nova_vm

Crate nova_vm 

Source
Expand description

§Nova JavaScript engine

Nova is a JavaScript engine focused on being lightweight, modular, and easy to embed. The engine’s architecture is built close to the ECMAScript specification in structure with the implementation relying on idiomatic Rust and data-oriented design over traditional JavaScript engine building strategies. Interpreter performance is also a goal, but not yet a high priority.

The engine is exposed as a library with an API for implementation in Rust projects which themselves must serve as a runtime for JavaScript code. The execution model is greatly inspired by Kiesel and LibJS.

§Basic usage

The engine has very little bells or whistles and is very easy to set up for one-off script runs or simple call-and-return instances. The engine uses the WTF-8 encoding internally for String storage, making interfacing with JavaScript look and act similar to normal Rust code.

use nova_vm::{ecmascript::{DefaultHostHooks, GcAgent}, engine::GcScope};
let mut agent = GcAgent::new(Default::default(), &DefaultHostHooks);
let realm = agent.create_default_realm();
let _ = agent.run_in_realm(&realm, |_agent, _gc| {
  // do work here
});

§Architecture

The engine’s public API relies on idiomatic Rust over traditional JavaScript engine building wisdom. This is most apparent in the Value type and its subvariants such as Object: instead of using NaN-boxing, NuN-boxing, or other traditional and known efficient strategies for building a dynamically typed language, Nova uses normal Rust enums carrying either on-stack data or a 32-bit handle to heap-allocated data. The only pointer that gets consistently passed through call stacks is the Agent reference, and handles are merely ways to access heap-allocated JavaScript data held inside the Agent.

Internally, the architecture and structure of the engine follows the ECMAScript specification but uses data-oriented design for the actual implementation. Data on the heap is allocated in homogenous (containing data of only one type) arenas with hot data split apart from cold data, and optional data stored behind keyed indirections using the arena’s associated 32-bit handle as the key, thus using no memory to store the default null case. The arenas are additionally compacted during garbage collection, trading some extra collection time for better runtime cache locality for hot data.

§Shortcomings and unexpected edge cases

Nova JavaScript engine is not perfect and has many shortcomings.

  1. The engine performance is acceptable, but it is not fast by any means.
  2. The Array implementation does not support sparse storage internally. Calling new Array(10 ** 9) will request an allocation for 1 billion JavaScript Values.
  3. The RegExp implementation does not support lookaheads, lookbehinds, or backreferences. It is always in UTF-8 / Unicode sets mode, does not support RegExp patterns containing unpaired surrogates, and its groups are slightly different from what the ECMAScript specification defines. In short: it is not compliant.
  4. Promise subclassing is currently not supported.
  5. The engine does not support WebAssembly execution.

Modules§

ecmascript
ECMAScript language
engine
Nova JavaScript engine
heap
Nova engine heap structures

Functions§

register_probes
Function that should be called as the very first thing in fn main() of any application using Nova JavaScript engine. This function registers USDT probes with the DTrace kernel module on OS’s that have one and is required for them to work. On other OS’s this is a no-op.