Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ let realm = agent.create_default_realm();
let _ = agent.run_in_realm(&realm, |_agent, _gc| {
// do work here
});
agent.gc();
```

## [Architecture]
Expand Down
1 change: 0 additions & 1 deletion nova_vm/src/ecmascript/execution/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,6 @@ pub trait HostHooks: core::fmt::Debug {
/// let _ = agent.run_in_realm(&realm, |_agent, _gc| {
/// // do work here
/// });
/// agent.gc();
/// ```
pub struct GcAgent {
agent: Agent,
Expand Down
81 changes: 80 additions & 1 deletion nova_vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,86 @@

#![cfg_attr(feature = "proposal-float16array", feature(f16))]
#![warn(missing_docs)]
#![doc = include_str!("../../README.md")]

//! # 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.
//!
//! ```rust
//! 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.
//! 1. The [`Array`] implementation does not support sparse storage internally.
//! Calling `new Array(10 ** 9)` will request an allocation for 1 billion
//! JavaScript [`Value`]s.
//! 1. 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.
//! 1. [`Promise`] subclassing is currently not supported.
//! 1. The engine does not support [WebAssembly] execution.
//!
//! [`Agent`]: crate::ecmascript::Agent
//! [`Array`]: crate::ecmascript::Array
//! [`RegExp`]: crate::ecmascript::RegExp
//! [`Promise`]: crate::ecmascript::Promise
//! [`Object`]: crate::ecmascript::Object
//! [`String`]: crate::ecmascript::String
//! [`Value`]: crate::ecmascript::Value
//! [WebAssembly]: https://webassembly.org
//! [WTF-8]: https://wtf-8.codeberg.page/
//! [JavaScript]: https://tc39.es/ecma262
//! [Kiesel]: https://codeberg.org/kiesel-js/kiesel
//! [LibJS]: https://github.com/LadybirdBrowser/ladybird/tree/master/Libraries/LibJS

pub mod ecmascript;
pub mod engine;
Expand Down
Loading