Overview

ENGINEERINGBOA JS ENGINE

Table of Contents

How I Got Into Boa
The Emoji Bug in URI DecodeHunting Silent DivergencesMy Workflow: Spec Line by Line

How I Got Into Boa

My coding journey started with C and C++, which made me curious about how things work under the hood. When I started web development, JavaScript's weird behaviors fascinated me. While building full-stack projects, I kept running into JS behaving unexpectedly. Instead of just working around it, I wanted to understand why.

In February of my 4th semester, I started learning Rust. In March, I found Boa - a project building a lightweight, embeddable JavaScript engine in Rust without Chrome's heavy V8 engine. That mission clicked immediately. I have never been a tutorial guy. I learn by reading official docs, breaking things, and fixing them myself. So I opened Boa's codebase and the ECMA-262 spec side by side and started reading.

The Emoji Bug in URI Decode

While reading through Boa's URI decode functions, something caught my eye. The code was using code_point_at to read characters from the string. But in the ECMA-262 specification (§19.2.6.6 Step 4.a), it clearly says: 'Let C be the code unit at index k within string.'

Code points and code units are not the same thing for non-BMP characters like emojis in UTF-16. Because of that single line, Boa was silently returning wrong results for any URI containing an emoji. I raised Issue #5166 and fixed it in PR #5168 by replacing code_point_at with code_unit_at. Core maintainer jedel1043 reviewed it, suggested a small improvement which I fixed the same day, and merged it. That was my first PR in Boa.

Hunting Silent Divergences

A lightweight engine only matters if it actually does what JavaScript says it should do. A TextDecoder ignoring a DataView byte offset, or a Headers object throwing a raw string instead of a TypeError - these bugs don't crash loudly; they break real-world applications silently.

I kept auditing the specs and finding gaps. In Fetch, I fixed Headers throwing strings instead of TypeErrors (PR #5177), enforced body rejections on GET/HEAD requests (PR #5201), and added status 205 checks (PR #5208). In Encoding, I fixed TextDecoder.decode() ignoring DataView offsets (PR #5172) and handling omitted input (PR #5174). In built-ins, I fixed toPrecision on subnormal floats like Number.MIN_VALUE (PR #5226) and Math.acosh for large inputs (PR #5230).

My Workflow: Spec Line by Line

I don't guess bugs. I carefully read the spec and fix exactly how the spec says it should behave. That is how I found bugs sitting in Boa unnoticed - not because they were hard to fix, but because finding them required reading the spec line by line.

Every PR I submit follows the exact same process:

01
Read the spec section of the target area.
02
Find the gap between what Boa does and what the spec says.
03
Raise an issue on GitHub with clear reproduction steps.
04
Fix the issue in a focused PR citing the exact spec section.
05
Add regression tests so the bug never comes back.
06
Run Test262 via CI to verify conformance changes.

Every PR moves the needle on Test262. For example, PR #5226 moved Boa's conformance from 95.43% to 95.44%, bringing failing tests down from 992 to 991. Finding these bugs requires patience and reading the spec line by line - and that is what I do.