Nativo

Nativo describes each built-in method once, then generates the six Rust surfaces (registration, validation, interpreter fast path, inline cache, JIT assumptions, and CruftScript type) from that one description, so they can never drift apart.

A single built-in method like String.prototype.charCodeAt is not one thing inside a JavaScript engine. It is installed on a prototype with a name, a length, and property flags. It validates its receiver and arguments. It has a fast path in the interpreter so a hot loop does not pay full call overhead. It has an inline-cache shape and a set of assumptions the JIT is allowed to make about it, plus the conditions under which compiled code must fall back. And in Cruft it also has a typed signature that the sound CruftScript language sees. That is six separate places, in three subsystems, that must all agree about one method.

In most engines those surfaces are written and maintained separately, and keeping them in agreement is a standing source of subtle bugs: the JIT assumes an arity the interpreter no longer enforces, or a fast path returns a shape the validation layer would have rejected. Cruft closes that gap with Nativo, its native-API manifest, which generates them. Each covered method is described once, in a manifest entry, and the six Rust surfaces are generated from that one description. They cannot drift apart, because none of them is written independently.

The one description, and the six surfaces

An entry names a method and states the facts about it once. From that entry, the generator emits the Rust that each subsystem compiles in:

Registrationhow the method appears on its prototype: property name, length, and the writable / enumerable / configurable flags
Validationthe receiver type and argument shape the method accepts
Interpreter fast paththe hot-intrinsic entry Exegesis dispatches to directly, skipping general call setup
Inline cachethe shape the interpreter's inline cache records for the call site
JIT expectationwhat LeJIT-compiled code may assume about the call, and the guard that deoptimizes when the assumption breaks
Stdlib signaturethe typed signature the sound CruftScript standard library exposes

The interpreter, LeJIT, and the CruftScript standard library then read these generated specs rather than each carrying its own copy. Because all six come from the same entry, they agree by construction: LeJIT cannot assume a charCodeAt arity the interpreter does not register, and the CruftScript signature cannot promise a return type the validation layer would reject.

Generation covers the specifications, not the work. Each fast path still has an authored Rust function that does the actual character lookup or trim; the manifest generates the entry that installs it, the flags around it, and the assumptions the JIT is allowed to make, then pairs that generated entry with the authored function. The description and the machinery around it are generated; the algorithm is authored.

What it covers today

The manifest currently drives about 153 hot built-in methods, the ones where interpreter speed and JIT assumptions matter most and where a drift between subsystems would be most costly, the hot String.prototype methods (charCodeAt, codePointAt, indexOf, startsWith, includes, toLowerCase, trim, and the rest) and hot Buffer accessors among them. Together these emit several thousand lines of Rust that no one edits directly.

Regenerating is the only way to change a covered method: the emitted files carry a do-not-edit notice, and a change means editing the entry and rerunning the generator. That is the property that makes the whole thing trustworthy. The generated surfaces are always exactly what the entry says, never a hand-edit that quietly diverged.

Why this is the shape

Generating code to fill in Rust is ordinary; the compatibility, serialization, and Unicode-table crates most projects depend on all do it. What the manifest adds is a single source of truth spanning subsystems that are usually maintained independently. The interpreter, the compiler, and the type surface of a whole separate language have to hold the same beliefs about a built-in for the runtime to be both fast and correct, and the cheapest way to guarantee they do is to stop writing those beliefs down more than once.

It is the same instinct as the rest of owning the stack: where a thing must be true in several places, make it true in one place and derive the rest.

Limitations

  • It covers the hot methods, not the whole runtime. Around 153 built-ins are driven by the manifest today; the large majority of the runtime's built-ins are still registered by hand. The manifest is applied where interpreter and JIT agreement pays off most, and it is an expanding front, not a finished one.
  • The fast-path functions are authored, not generated. Generation owns each method's registration, flags, validation shape, and JIT expectations, not its implementation. A bug in the character-lookup algorithm is a bug in authored Rust; the manifest only guarantees the surfaces around it agree.
  • The entry format is still settling. The manifest is young (Cruft is 0.0.10), and the exact shape of an entry and the set of surfaces it emits are still changing as more of the built-in surface is brought under it.