<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Boa</title><link>https://blog.ast.moe/en/tags/boa/</link><description>Recent posts: Gorimuchu</description><generator>Hugo</generator><item><title>After implementing Omoikane’s DOM and exception notifications, we ended up investigating copying and garbage‑collection lifetimes as well.</title><link>https://blog.ast.moe/en/blog/2026-10-10/</link><pubDate>Sat, 10 Oct 2026 17:42:29 +0900</pubDate><guid>https://blog.ast.moe/en/blog/2026-10-10/</guid><description>&lt;p&gt;We added DOM operations such as &lt;code&gt;before()&lt;/code&gt; and &lt;code&gt;replaceChildren()&lt;/code&gt; to Omoikane, along with &lt;code&gt;window.onerror&lt;/code&gt; and notifications for unhandled Promise rejections. [&lt;a href="https://github.com/ieee0824/omoikane/pull/1322"&gt;PR #1322&lt;/a&gt;](&lt;a href="https://github.com/ieee0824/omoikane/pull/1322"&gt;https://github.com/ieee0824/omoikane/pull/1322&lt;/a&gt;) This is about that pull request. The initial issue was straightforward: the page lacked the APIs it normally calls. However, as we progressed with implementation and testing, we ended up fixing issues such as copying sibling lists when inserting HTML text, rebuilding the entire document after UTF‑16 appends, creating unnecessary iframe realms, and even addressing insufficient GC roots for Promises.&lt;/p&gt;</description></item><item><title>WeakMap and Generational Garbage Collection</title><link>https://blog.ast.moe/en/blog/2026-10-08-2/</link><pubDate>Thu, 08 Oct 2026 21:52:45 +0900</pubDate><guid>https://blog.ast.moe/en/blog/2026-10-08-2/</guid><description>&lt;p&gt;Opening &lt;code&gt;https://tokyo6.tokyo/&lt;/code&gt; with Omoikane caused a bug where the script terminated with a SIGSEGV during execution. Issue #1223 (&lt;a href="https://github.com/ieee0824/omoikane/issues/1223"&gt;issue #1223&lt;/a&gt;) reproduces the problem not only in the GUI but also in the screenshot feature that renders the screen to an image. The backtrace from the debug build reproduced on a Linux aarch64 Docker development environment with Xvfb showed that Boa’s garbage collector halted while traversing references to an object.&lt;/p&gt;
&lt;p&gt;The fix in &lt;a href="https://github.com/ieee0824/omoikane/pull/1260"&gt;PR #1260&lt;/a&gt; (&lt;a href="https://github.com/ieee0824/omoikane/pull/1260"&gt;PR #1260&lt;/a&gt;) addressed the combination of an ephemeron—a conditional reference—and the generational garbage collector. A young object that was referenced by an older object was being reclaimed during the minor GC that followed a major GC. Subsequently, the major GC followed a reference that had already been freed, causing a crash.&lt;/p&gt;</description></item><item><title>The object returned by Boa’s getter was collected by the garbage collector while the inline cache was being updated.</title><link>https://blog.ast.moe/en/blog/2026-09-30/</link><pubDate>Wed, 30 Sep 2026 08:12:00 +0900</pubDate><guid>https://blog.ast.moe/en/blog/2026-09-30/</guid><description>&lt;p&gt;When running the test for a custom element associated with a form in Omoikane’s Web Platform Tests (WPT), it caused a SIGSEGV. The first occurrence was in a configuration that included the JIT, so we initially suspected an interaction between Boa’s JIT or its garbage collector. However, even when the JIT was disabled, the same crash could be reproduced (&lt;a href="https://github.com/ieee0824/omoikane/issues/858#issuecomment-5890658215"&gt;issue #858&lt;/a&gt;), and ultimately the problem lay in a tiny interval between when the getter’s returned object was produced and when it was stored in the VM’s registers.&lt;/p&gt;</description></item><item><title>Since generating realms with Omoikane was slow, I looked into Boa’s scope lookup and lexical analysis.</title><link>https://blog.ast.moe/en/blog/2026-09-29-2/</link><pubDate>Tue, 29 Sep 2026 18:25:00 +0900</pubDate><guid>https://blog.ast.moe/en/blog/2026-09-29-2/</guid><description>&lt;p&gt;In the blog post investigating Omoikane’s CI wait times, we wrote about avoiding heavy verification for changes that only affect documentation and about revisiting the build cache. Separate from that, the tests that actually needed to be run were also taking a considerable amount of time. (&lt;a href="https://blog.ast.moe/en/blog/2026-09-29/"&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Omoikane uses Boa to execute JavaScript. Each time a JavaScript realm is created for a page or an iframe, a large script that sets up the DOM API is run. This processing accounted for a substantial portion of the test runtime. In &lt;a href="https://github.com/ieee0824/omoikane/issues/1154"&gt;Issue #1154&lt;/a&gt;, instead of reducing the number of tests or realms, we investigated this initialization itself.&lt;/p&gt;</description></item><item><title>A SIGSEGV occurred after garbage collection because the iterator function passed to Boa’s Array.from was not properly retained.</title><link>https://blog.ast.moe/en/blog/2026-09-25/</link><pubDate>Fri, 25 Sep 2026 08:46:00 +0900</pubDate><guid>https://blog.ast.moe/en/blog/2026-09-25/</guid><description>&lt;p&gt;While running Omoikane’s Acid3 test, the process hit a SIGSEGV under the baseline JIT configuration on macOS ARM64. I briefly mentioned this in the earlier blog post about Omoikane updates, but the cause wasn’t the test itself nor the JIT’s machine‑code generation; it lay in the Boa code we’re incorporating, specifically in the &lt;code&gt;Array.from()&lt;/code&gt; section. Omoikane incorporates Boa’s source code together with the browser‑side implementation, so the fix was also applied to the engine that pulls in that code. (&lt;a href="https://blog.ast.moe/en/blog/2026-09-20/"&gt;source&lt;/a&gt;)&lt;/p&gt;</description></item><item><title>I investigated why Acid3 was crashing due to memory errors in Omoikane’s baseline JIT.</title><link>https://blog.ast.moe/en/blog/2026-09-13/</link><pubDate>Sun, 13 Sep 2026 20:20:51 +0900</pubDate><guid>https://blog.ast.moe/en/blog/2026-09-13/</guid><description>&lt;p&gt;While working on implementing CSS in my own browser, Omoikane (&lt;a href="https://github.com/ieee0824/omoikane"&gt;source&lt;/a&gt;), Acid3 began crashing due to memory errors.&lt;/p&gt;
&lt;p&gt;The problem only occurs when the baseline JIT is enabled; it runs fine with the interpreter.&lt;/p&gt;
&lt;p&gt;Furthermore, Omoikane’s Acid3 runner has two execution modes, Faithful and DirectDrive. Faithful completes all 100 points, but then it crashes during DirectDrive.&lt;/p&gt;
&lt;p&gt;The failure manifests differently depending on the environment.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Environment&lt;/th&gt;
&lt;th&gt;Observed failure&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;x86_64 Linux&lt;/td&gt;
&lt;td&gt;SIGSEGV&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ARM64 Linux&lt;/td&gt;
&lt;td&gt;SIGABRT, ~60 GB allocation, SIGSEGV on rerun&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ARM64 macOS&lt;/td&gt;
&lt;td&gt;SIGSEGV, SIGBUS on rerun&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Even though it’s the same test, the signals differ.&lt;/p&gt;</description></item><item><title>I forgot to keep a Promise alive in Boa, which broke the malloc.</title><link>https://blog.ast.moe/en/blog/2026-09-10-4/</link><pubDate>Thu, 10 Sep 2026 20:37:07 +0900</pubDate><guid>https://blog.ast.moe/en/blog/2026-09-10-4/</guid><description>&lt;p&gt;While running Boa’s Test262, the test occasionally failed with exit code 134.&lt;/p&gt;
&lt;p&gt;The logs show the following errors:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;malloc(): unsorted double linked list corrupted
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The issue is the “normal Test262 release run is aborted due to an allocator consistency error” (&lt;a href="https://github.com/ieee0824/omoikane/issues/638"&gt;issue #638&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;At first, I assumed some recent change was corrupting memory somewhere. However, because Test262 runs a large number of tests in parallel, the logs alone don’t reveal which specific test is causing the problem.&lt;/p&gt;</description></item><item><title>Boa incorrectly judged stack usage due to ASAN's fake stack.</title><link>https://blog.ast.moe/en/blog/2026-09-10-3/</link><pubDate>Thu, 10 Sep 2026 20:14:12 +0900</pubDate><guid>https://blog.ast.moe/en/blog/2026-09-10-3/</guid><description>&lt;p&gt;In the previous article, we fixed the issue where Boa’s parser exhausted a 2 MiB stack. (&lt;a href="https://blog.ast.moe/en/blog/2026-09-10-2/"&gt;related article&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;We reduced the frame size during recursion and made it return an error for inputs that are too deep. With a normal build, the original Test262 now also passes within the 2 MiB limit.&lt;/p&gt;
&lt;p&gt;When we continued diagnosing with AddressSanitizer (ASAN) in that state, it started rejecting even shallow inputs.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;parser recursion limit exceeded
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The protection we added to prevent stack exhaustion was stopping prematurely, even though the stack hadn’t been fully used. This concerns &lt;a href="https://github.com/ieee0824/omoikane/issues/640"&gt;Issue #640&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Boa's parser exhausted a 2 MiB stack</title><link>https://blog.ast.moe/en/blog/2026-09-10-2/</link><pubDate>Thu, 10 Sep 2026 19:58:13 +0900</pubDate><guid>https://blog.ast.moe/en/blog/2026-09-10-2/</guid><description>&lt;p&gt;While running Test262 before importing Boa into Omoikane, we discovered a case where an unoptimized parser aborts due to a stack overflow (&lt;a href="https://github.com/ieee0824/omoikane/issues/633"&gt;issue #633&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The failure occurred in Test262’s &lt;a href="https://github.com/tc39/test262/blob/a073f479f80b336256b7fc4e04700c827293e2fe/test/staging/sm/regress/regress-672893.js"&gt;&lt;code&gt;regress-672893.js&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It wasn’t a matter of nesting tens of thousands of invalid JavaScript statements. It was valid JavaScript with about fifteen levels of nested function expressions.&lt;/p&gt;
&lt;p&gt;If we omit the structural details, the code looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;function f() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return function () {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return function () {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...continues in the same pattern up to 15 steps...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return function (a) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; var v = a;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return function () { return v; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;f()()() ... ()(42)();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When this code is passed to a Boa built with the dev profile and the thread stack is set to 2 MiB, the parser triggers a stack overflow and exits with status 134.&lt;/p&gt;</description></item></channel></rss>