Making Generated JavaScript Inline-Caching Friendly in ReScript

In this post, I want to explain how ReScript (formerly BuckleScript) improves JavaScript performance by using type information to generate predictable runtime representations.

Modern JavaScript engines like V8 heavily optimize based on object shapes. When those shapes stay consistent, engines can apply inline caching, which leads to significant performance gains.

ReScript leans into this by ensuring the JavaScript it generates is both idiomatic and engine-friendly.


Why Encoding Matters

JavaScript engines optimize property access based on how objects look at runtime.

If object shapes change often:

  • Inline caches break
  • Property access slows down
  • Debugging becomes harder

ReScript avoids this by guaranteeing:

  • Similar data always has the same shape
  • Variant representations are predictable
  • Generated JavaScript remains readable

Record Encoding (Stable Objects)

Records in ReScript compile directly to JavaScript objects.

Example ReScript record:

1type int64 = { loBits: int [@bs.as "lo"], hiBits: int [@bs.as "hi"] } 2let value = { hiBits: 33, loBits: 32 } 3let sum = ({ loBits, hiBits }) => loBits + hiBits

Generated JavaScript looks like:

1var value = { lo: 32, hi: 33 } 2function sum(param) { return param.lo + param.hi }

Why this works well:

  • Object shapes are consistent
  • Property names are stable
  • Debuggers show meaningful structures

Variant Encoding (Tagged Unions)

Variants are encoded using different strategies depending on whether they carry data.

Variants Without Payload

These compile to simple numbers.

Rescript:

1type color = | Red | Blue | Green

Generated JavaScript:

1Red = 0, Blue = 1, Green = 2

This representation is compact and fast.


Variants With Payload

Variants that carry data compile to objects with a stable layout.

ReScript:

1type tree = | Empty | Node(tree, int, tree) 2let t = Node(Empty, 3, Empty)

Generated JavaScript:

1var t = { TAG: 0, _0: 0, _1: 3, _2: 0 }

Each object:

  • Uses the same fields
  • Preserves stable shapes
  • Works well with inline caching

Optimized Variant Encoding (Single Payload)

When only one variant carries data, ReScript skips the TAG field entirely.

ReScript:

1type list = | Nil | Cons(int, list) 2let xs = Cons(1, Nil)

Generated JavaScript:

1var xs = { _0: 1, _1: 0 }

This reduces object size while keeping pattern matching predictable.


List Encoding for Debugging

Lists can also be encoded using clearer field names:

1{ hd: 1, tl: { hd: 2, tl: { hd: 3, tl: 0 } } }

This improves debuggability while remaining efficient for JavaScript engines.


Polymorphic Variants

Polymorphic variants also generate stable shapes.

ReScript:

1let v = `hello(3)

Generated JavaScript:

1var v = { HASH: someNumber, VAL: 3 }

These shapes remain consistent and engine-optimizable.


Final Thoughts

ReScript’s approach to encoding data is about more than performance. It also improves:

  • Debugging experience
  • Predictability
  • Confidence in refactors

By combining strong typing with JavaScript-friendly output, ReScript produces code that runs fast and stays understandable.

This balance is what makes ReScript especially appealing for long-lived, production frontend systems.