<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>tech blog // jared hirsch // ¯\_(ツ)_/¯</title>
    <description>tech blog // jared hirsch // ¯\_(ツ)_/¯
</description>
    <link>https://6a68.net/</link>
    <atom:link href="https://6a68.net/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Thu, 28 May 2026 22:31:28 +0000</pubDate>
    <lastBuildDate>Thu, 28 May 2026 22:31:28 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Gecko C++ notes</title>
        <description>&lt;p&gt;Probably not useful for anybody, but something I told myself I’d do: share out some C++ notes.&lt;/p&gt;

&lt;p&gt;These notes are based on the 2016? Mozilla C++ and Gecko onboarding presentation by froydnj: https://mozilla.hosted.panopto.com/Panopto/Pages/Embed.aspx?id=65922cea-26e0-4d3b-a5da-ac1600012f45&lt;/p&gt;

&lt;p&gt;I don’t know why this talk is set to Mozilla-private, I’m working on getting it made public.&lt;/p&gt;

&lt;p&gt;Anyway here we go.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Basic topics to cover:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Subsystems in Gecko&lt;/li&gt;
  &lt;li&gt;XPCOM strings and datatypes&lt;/li&gt;
  &lt;li&gt;infallible alloc&lt;/li&gt;
  &lt;li&gt;coding style&lt;/li&gt;
  &lt;li&gt;C++ guidelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additional topics suggested by Gecko experts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Refcounting&lt;/li&gt;
  &lt;li&gt;Smart pointers&lt;/li&gt;
  &lt;li&gt;IDLs: XPIDL, WebIDL, IPDL&lt;/li&gt;
  &lt;li&gt;Electrolysis (e10s) (TODO: this video predates fission and should be brought up to date)&lt;/li&gt;
  &lt;li&gt;NSPR&lt;/li&gt;
  &lt;li&gt;Threading&lt;/li&gt;
  &lt;li&gt;C++ visibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Outline of the talk:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;What happens when I click a link? (Intro to subsystems and overall network and rendering pipeline)&lt;/li&gt;
  &lt;li&gt;Nuts and bolts of Gecko C++&lt;/li&gt;
  &lt;li&gt;Code generation&lt;/li&gt;
  &lt;li&gt;Memory management
    &lt;ul&gt;
      &lt;li&gt;Smart pointers&lt;/li&gt;
      &lt;li&gt;Reference counting schemes&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Gecko C++ data structures&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;what-happens-when-i-click-a-link&quot;&gt;What happens when I click a link?&lt;/h2&gt;

&lt;p&gt;Sequence: Network -&amp;gt; Parser -&amp;gt; DOM -&amp;gt; Styles -&amp;gt; Layout -&amp;gt; Display List -&amp;gt; Paint -&amp;gt; Composite&lt;/p&gt;

&lt;p&gt;Docshell is where it all begins: Docshell sets up, then network loads&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/docshell&lt;/code&gt; directory (see also &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/uriloader&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;URI loading starts&lt;/li&gt;
  &lt;li&gt;Handles navigating between docs (back-forward movement)&lt;/li&gt;
  &lt;li&gt;Starts doc loading&lt;/li&gt;
  &lt;li&gt;Sets things up for network&lt;/li&gt;
  &lt;li&gt;Manages session history&lt;/li&gt;
  &lt;li&gt;See also uriloader (we probably should merge these eventually)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Networking code&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/netwerk&lt;/code&gt; dir (the misspelling is deliberate and historical)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/netwerk/dns&lt;/code&gt; has DNS-related code
    &lt;ul&gt;
      &lt;li&gt;We use the OS for DNS resolution&lt;/li&gt;
      &lt;li&gt;We add in other stuff&lt;/li&gt;
      &lt;li&gt;DNS is done off the main thread and parallelized&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/netwerk/protocol&lt;/code&gt; has code for protocols (HTTP, FTP, WebSocket, …)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/netwerk/cache2&lt;/code&gt; handles document caching
    &lt;ul&gt;
      &lt;li&gt;We cache documents on disk for speed&lt;/li&gt;
      &lt;li&gt;There’s old code in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/netwerk/cache&lt;/code&gt;, unclear why it’s not deleted. Ignore it.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/netwerk/cookie&lt;/code&gt; manages cookies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the network returns data, DocShell sets up listeners to handle the results.&lt;/p&gt;

&lt;p&gt;Next: the parser, which handles the network response.&lt;/p&gt;

&lt;h3 id=&quot;parsing&quot;&gt;Parsing&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/parser&lt;/code&gt; directory&lt;/li&gt;
  &lt;li&gt;Multiple parsers:
    &lt;ul&gt;
      &lt;li&gt;XML (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/parser/xm&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/parser/expat&lt;/code&gt;)&lt;/li&gt;
      &lt;li&gt;old-style HTML &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/parser/htmlparser&lt;/code&gt;, only used for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;about:blank&lt;/code&gt; as of 2016&lt;/li&gt;
      &lt;li&gt;HTML5 (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/parser/html&lt;/code&gt;)&lt;/li&gt;
      &lt;li&gt;Old-style parsers had a lot of quirks at handling parsing errors&lt;/li&gt;
      &lt;li&gt;HTML5 is much better specified for error handling&lt;/li&gt;
      &lt;li&gt;Expat is ~20 years old, we use it for XML parsing
        &lt;ul&gt;
          &lt;li&gt;It’s very simple and very fast&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As the parser parses, it builds DOM nodes for all elements
Loading other formats (CSS, JS, images) is driven by the parser, but handled elsewhere.&lt;/p&gt;

&lt;h3 id=&quot;dom&quot;&gt;DOM&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dom&lt;/code&gt; directory&lt;/li&gt;
  &lt;li&gt;Absolutely massive directory
    &lt;ul&gt;
      &lt;li&gt;Documents, elements all live in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dom/base&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dom/html&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Various web APIs often have individual subdirectories, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dom/indexedDB&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;WebAPI definitions are imported into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dom/webidl&lt;/code&gt; for spec conformance verification
        &lt;ul&gt;
          &lt;li&gt;These definitions are also used to code generate JS bindings in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dom/bindings&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DOM builds up the linked tree of DOM nodes
Next, we need to position nodes on a 2D page.&lt;/p&gt;

&lt;h3 id=&quot;layout&quot;&gt;Layout&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Translates the DOM tree to 2D canvas.&lt;/li&gt;
  &lt;li&gt;Every visible DOM node gets its own Frame, then Layout figures out how to position the Frames relative to each other&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/layout&lt;/code&gt; directory&lt;/li&gt;
  &lt;li&gt;also massive
    &lt;ul&gt;
      &lt;li&gt;Our CSS implementation is in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/layout/style&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/base&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/generic&lt;/code&gt;: Frames (box around each element), Display Lists (organizing Frames so we can paint them quickly)&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/layout/svg&lt;/code&gt; holds the SVG code&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/layout/xul&lt;/code&gt; XUL&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Given a bunch of boxes, now we need to paint them to the screen.&lt;/p&gt;

&lt;h3 id=&quot;graphics&quot;&gt;Graphics&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/gfx&lt;/code&gt; directory&lt;/li&gt;
  &lt;li&gt;also large, but mainly because we use third-party libraries&lt;/li&gt;
  &lt;li&gt;We have our own code for some 2D primitives in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/gfx/2d&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/gfx/thebes&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Thebes: our old way of rendering to the screen
    &lt;ul&gt;
      &lt;li&gt;old enough that it doesn’t map well to modern graphics APIs&lt;/li&gt;
      &lt;li&gt;rewrite in progress (as of 2016)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Layers for compositing in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/gfx/layers&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;All the boxes we had get organized into Layers&lt;/li&gt;
      &lt;li&gt;The static parts of the page are grouped together as one layer, paint that into a texture on the graphics card&lt;/li&gt;
      &lt;li&gt;Things that are changing get their own layers, sent off as textures to the graphics card&lt;/li&gt;
      &lt;li&gt;Ship all the layers off to the GPU to be squashed together and composited all at once&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Lots of third-party graphics code managed by the gfx team:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/angle&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/cairo&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/graphite2&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/harfbuzz&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/ots&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/skia&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/ycbcr&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this introductory talk, we’re skipping the final stages of rendering.&lt;/p&gt;

&lt;p&gt;What else is in Gecko?&lt;/p&gt;

&lt;p&gt;Storage in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/storage&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;We use SQLite for many things&lt;/li&gt;
  &lt;li&gt;IndexedDB, localStorage use SQLite&lt;/li&gt;
  &lt;li&gt;Browser history (the Places DB)&lt;/li&gt;
  &lt;li&gt;Cookies&lt;/li&gt;
  &lt;li&gt;ServiceWorker cache API is backed by SQLite&lt;/li&gt;
  &lt;li&gt;Not an ORM. We run SQL strings everywhere.&lt;/li&gt;
  &lt;li&gt;MozStorage provides a nice multithreaded API over SQLite
    &lt;ul&gt;
      &lt;li&gt;e.g. run query in background thread, then return results async&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Images, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/image&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;We wrote a .bmp decoder&lt;/li&gt;
  &lt;li&gt;For newer formats, we use third-party libraries: libpng, libjpeg, libgif&lt;/li&gt;
  &lt;li&gt;Decoding images &amp;amp; transforming into suitable form for the gfx code&lt;/li&gt;
  &lt;li&gt;Decoding is done off the main thread&lt;/li&gt;
  &lt;li&gt;We use a thread pool to parallelize up to the computer’s limits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Media in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/media&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Largely imported code for sound, image, video handling&lt;/li&gt;
  &lt;li&gt;Also where (imported) WebRTC implementation lives&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Widget code in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/widget&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Interface between Gecko and OS native event and window handling&lt;/li&gt;
  &lt;li&gt;Abstraction layer (generic IDLs)&lt;/li&gt;
  &lt;li&gt;Separate directories for various platforms:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/android&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/cocoa&lt;/code&gt; (mac), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/donk&lt;/code&gt; (B2G, now deleted as of 2021), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/gtk&lt;/code&gt; (linux), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uikit&lt;/code&gt; (iOS), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/windows&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;IPC (inter-process communication) code lives in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/ipc&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Code for managing multiple processes&lt;/li&gt;
  &lt;li&gt;Electrolysis (e10s) separates out browsing duties:
    &lt;ul&gt;
      &lt;li&gt;Parent process (handles user interaction)&lt;/li&gt;
      &lt;li&gt;Child proc: web content code, JS, etc. for responsiveness &amp;amp; security&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;This code originally came from Chromium ~5 years ago (i.e. 2011 I guess?)
    &lt;ul&gt;
      &lt;li&gt;It’s now been modified beyond all mergeability. An unintentional fork.&lt;/li&gt;
      &lt;li&gt;If you hit bugs, likely worth looking upstream for existing fixes.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Big chunks here:
    &lt;ul&gt;
      &lt;li&gt;sending / receiving messages&lt;/li&gt;
      &lt;li&gt;Object serialization / deserialization&lt;/li&gt;
      &lt;li&gt;A separate event loop (more on this in a bit)&lt;/li&gt;
      &lt;li&gt;IPDL code generator&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JavaScript engine in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/js&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Our JS implementation: parsing, interpretation, JIT compiler, GC, etc.&lt;/li&gt;
  &lt;li&gt;To encourage embedding, we have public interfaces in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/js/public&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;But we don’t invest in this right now&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;The source code lives in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/js/src&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;XPConnect: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/js/xpconnect&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;“Deep Magic”: manages reflection of objects between JS and C++&lt;/li&gt;
  &lt;li&gt;Also defines our security architecture for JS
    &lt;ul&gt;
      &lt;li&gt;See Script Security in source docs for details&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MFBT &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/mfbt&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;“Mozilla Framework Based on Templates” (backronym and quite a stretch)&lt;/li&gt;
  &lt;li&gt;Code shared between Gecko and the JS engine
    &lt;ul&gt;
      &lt;li&gt;Classes we find useful&lt;/li&gt;
      &lt;li&gt;Polyfills for C++ stdlib things&lt;/li&gt;
      &lt;li&gt;The stdlib is inconsistent across platforms, so we have code to smooth it out&lt;/li&gt;
      &lt;li&gt;Close to C++11, aiming to delete large chunks of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/mfbt&lt;/code&gt; someday&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;XPCOM &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/xpcom&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;“Cross-platform COM” (component object model)&lt;/li&gt;
  &lt;li&gt;Idea: use code in multiple languages via shared language-agnostic interfaces
    &lt;ul&gt;
      &lt;li&gt;This was inspired by some Microsoft ideas from the 90s&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;We tried to do this across platforms, with varying degrees of success.&lt;/li&gt;
  &lt;li&gt;Lots of building blocks in here:
    &lt;ul&gt;
      &lt;li&gt;Data structures (arrays, hashtables, strings)&lt;/li&gt;
      &lt;li&gt;Core event loop (timers, threads)
        &lt;ul&gt;
          &lt;li&gt;Main thread and nonmain threads&lt;/li&gt;
          &lt;li&gt;Interacts with IPC event loop in various ways&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Parts of the JS interface to chrome code (XPConnect uses this stuff)
        &lt;ul&gt;
          &lt;li&gt;Interacts with XPConnect code, mostly machine-dependent parts&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Not quite complete abstract IO interface (stream abstraction that provides bytes, etc)
        &lt;ul&gt;
          &lt;li&gt;Most implementations of the abstract interface live in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/netwerk&lt;/code&gt; for historical reasons&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Cycle collector: part of the reference counting memory management code
        &lt;ul&gt;
          &lt;li&gt;Much more on this later in the talk&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NSPR &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/nspr&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Netscape Portable Runtime, 20+ years old&lt;/li&gt;
  &lt;li&gt;Abstracts threads, locks, I/O, logging, etc.&lt;/li&gt;
  &lt;li&gt;We use NSPR when it’s convenient
    &lt;ul&gt;
      &lt;li&gt;Sometimes we have nice wrappers (XPCOM has other nice wrappers for some threading stuff)&lt;/li&gt;
      &lt;li&gt;Sometimes we use things directly (I/O)&lt;/li&gt;
      &lt;li&gt;Sometimes stdlib has better alternatives&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Slowly working on removing NSPR
    &lt;ul&gt;
      &lt;li&gt;NSPR is a separate repo and team from Gecko&lt;/li&gt;
      &lt;li&gt;Separate release schedule, etc.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;part-2-gecko-c&quot;&gt;Part 2: Gecko C++&lt;/h2&gt;

&lt;p&gt;C++ Style Guide&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We have a style guide&lt;/li&gt;
  &lt;li&gt;Not all code conforms to the style guide
    &lt;ul&gt;
      &lt;li&gt;We’re working on it&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Please use the style guide for new code
    &lt;ul&gt;
      &lt;li&gt;Follow local conventions when necessary&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dom&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/layout&lt;/code&gt; are stricter than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/gfx&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clang-format&lt;/code&gt; if you like&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;C++ Features&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We don’t use exceptions
    &lt;ul&gt;
      &lt;li&gt;Historically, exceptions weren’t good on some platforms&lt;/li&gt;
      &lt;li&gt;They’ve gotten better, but converting Gecko to be exception-safe would be a huge chore&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;We don’t use RTTI (dynamic_cast, e.g.)
    &lt;ul&gt;
      &lt;li&gt;Bloat, doesn’t work with JS-implemented things&lt;/li&gt;
      &lt;li&gt;We already have an equivalent dynamic cast that’s JS compatible&lt;/li&gt;
      &lt;li&gt;RTTI not supported on Android&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;We have a page with our C++ feature support matrix across C++ versions and different compilers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Brief note on portability&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Across platforms, rate of new feature adoption differs, quality of implementation differs&lt;/li&gt;
  &lt;li&gt;Guarantees provided by interfaces may not be strong enough for us
    &lt;ul&gt;
      &lt;li&gt;e.g. we need memory reporting, std::vector doesn’t support this&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Hence, we reimplement the wheel in some places&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;C++ std:: classes&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Historically, we avoid std:: things&lt;/li&gt;
  &lt;li&gt;We don’t use exceptions, std does&lt;/li&gt;
  &lt;li&gt;It’s not necessarily available everywhere&lt;/li&gt;
  &lt;li&gt;Please use Gecko versions if possible&lt;/li&gt;
  &lt;li&gt;Please file bugs on Gecko versions if you find an API annoying&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Infallible allocation (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new T(...)&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new T[]&lt;/code&gt;)&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;By convention, if out of memory, allocation will crash, rather than returning a null pointer&lt;/li&gt;
  &lt;li&gt;We don’t return null, so we never need to rely on consistent null-checking&lt;/li&gt;
  &lt;li&gt;Useful for debugging things
    &lt;ul&gt;
      &lt;li&gt;e.g. if you try to allocate 100MB, crash immediately.&lt;/li&gt;
      &lt;li&gt;Otherwise, you get a null pointer back, sometime later you may dereference a null pointer–but it’s very hard to see how/where that happened.&lt;/li&gt;
      &lt;li&gt;So, this makes things simpler to debug&lt;/li&gt;
      &lt;li&gt;Also shorter: no need for lots of null checks&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;If you need an array but don’t control the allocation amount, we do have options
    &lt;ul&gt;
      &lt;li&gt;Fallible allocation: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new (fallible) T(...)&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nothrow&lt;/code&gt; in stdlib, predates it&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;C++ Visibility&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;We ship one big shared library, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xul.dll&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/xul.so&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Improves startup time&lt;/li&gt;
  &lt;li&gt;Exporting symbols from XUL is expensive
    &lt;ul&gt;
      &lt;li&gt;Runtime penalties, size penalties&lt;/li&gt;
      &lt;li&gt;Exposed interface penalties (malware hooks, etc)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Strive to export as little as possible
    &lt;ul&gt;
      &lt;li&gt;Generally the Right Thing happens by default&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Threads&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Main (UI) thread
    &lt;ul&gt;
      &lt;li&gt;Handles all user interaction, most content stuff&lt;/li&gt;
      &lt;li&gt;Important to avoid long blocking operations&lt;/li&gt;
      &lt;li&gt;Particularly important to avoid I/O on the main thread&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Lots of (mostly idle) helper threads
    &lt;ul&gt;
      &lt;li&gt;SQLite, media/image decoding, network cache, JS JIT compilation, JS GC, timers&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;3-code-generation&quot;&gt;3. Code Generation&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Used extensively in Gecko&lt;/li&gt;
  &lt;li&gt;3 main kinds of code generation
    &lt;ol&gt;
      &lt;li&gt;XPIDL: old bindings between JS and C++&lt;/li&gt;
      &lt;li&gt;IPDL: multi-process communication&lt;/li&gt;
      &lt;li&gt;WebIDL: new way of doing bindings between JS and C++&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;We have other, one-off code generators throughout the tree&lt;/li&gt;
  &lt;li&gt;All written in Python&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;XPIDL files&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Most useful for understanding how we get from JS to C++&lt;/li&gt;
  &lt;li&gt;“Cross-platform IDL”&lt;/li&gt;
  &lt;li&gt;Defining interfaces for either C++ or JS to implement&lt;/li&gt;
  &lt;li&gt;Generates C++ class boilerplate&lt;/li&gt;
  &lt;li&gt;Generates metadata for calling into C++ from JS (argument conversions)&lt;/li&gt;
  &lt;li&gt;Docs on MDN (RIP, TODO find them and pull into firefox docs somewhere)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;XPIDL: Generated code&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Generates headers for each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.idl&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$OBJDIR/dist/include&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsIFile.idl&lt;/code&gt; generates &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsIFile.h&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;IDL can define multiple interfaces per file =&amp;gt; generated header will have multiple class definitions&lt;/li&gt;
  &lt;li&gt;Each interface nsIFoo generates:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsIFoo&lt;/code&gt; class definition (empty methods)&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_DECL_IFOO&lt;/code&gt; macro for declaring all of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsIFoo&lt;/code&gt;’s interface in C++&lt;/li&gt;
      &lt;li&gt;Every interface has a UUID, there are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_IFILE_IID&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_IFILE_STR&lt;/code&gt; macros for the UUID&lt;/li&gt;
      &lt;li&gt;other macros, rarely needed&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some IDL -&amp;gt; C++ examples:&lt;/p&gt;

&lt;p&gt;IDL: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const unsigned long NORMAL_FILE_TYPE=0;&lt;/code&gt; (note: you don’t get strongly-typed enums)
C++: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enum { NORMAL_FILE_TYPE=0 };&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;IDL: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;void append(in AString node);&lt;/code&gt;
C++: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_IMETHOD Append(const nsAString&amp;amp;);&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Note the IDL parameters need to be annotated with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;in&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;out&lt;/code&gt; to indicate if they are passed in or received out&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;IDL: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bool exists();&lt;/code&gt;
C++: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_IMETHOD Exists(bool*);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;IDL: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;readonly attribute long long fileSize;&lt;/code&gt;
C++: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_IMETHOD GetFileSize(int64_t*);&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;By convention, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;readonly&lt;/code&gt; attributes return a getter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;IDL: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attribute AString leafName;&lt;/code&gt;
C++: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_IMETHOD GetLeafName(nsAString&amp;amp;);&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_IMETHOD SetLeafName(const nsAString&amp;amp;)&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;By convention, modifiable attributes generate getter and setter in C++&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;By convention, return values are a pointer.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_IMETHOD&lt;/code&gt; is short for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virtual nsresult&lt;/code&gt; + windows-specific goo&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsresult&lt;/code&gt; is our status code
    &lt;ul&gt;
      &lt;li&gt;Success case: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_OK&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;Please don’t use the other success values&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Failure: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_ERROR_FAILURE&lt;/code&gt; and many others
        &lt;ul&gt;
          &lt;li&gt;Please return the most specific error available&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Test the return value with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_SUCCEEDED(val)&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_FAILED(val)&lt;/code&gt;, don’t check directly&lt;/li&gt;
      &lt;li&gt;Complete list of errors: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/xpcom/base/ErrorList.h&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Methods&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Return values are passed through outparams&lt;/li&gt;
  &lt;li&gt;Only set outparam when you’re returning &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_OK&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Don’t use the outparam at caller until you check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_SUCCEEDED&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Always propagate errors to caller(s)&lt;/li&gt;
  &lt;li&gt;XPConnect maps errors to JS exceptions automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Getters / Setters&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Both can fail&lt;/li&gt;
  &lt;li&gt;Same outparam convention as methods&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;ipdl&quot;&gt;IPDL&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;IPDL files describe multi-process messaging “protocols
    &lt;ul&gt;
      &lt;li&gt;List of messages sent by parent or child&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Code generator generates the uninteresting, repetitive parts
    &lt;ul&gt;
      &lt;li&gt;e.g. serialization / deserialization&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Protocols are sorted into a hierarchy
    &lt;ul&gt;
      &lt;li&gt;e.g. PContent does top-level e10s per tab&lt;/li&gt;
      &lt;li&gt;PContent manages other protocols&lt;/li&gt;
      &lt;li&gt;Similarly, child has its own hierarchy / tree of protocols&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Provides C++ structure for the interesting parts (defines virtual handler methods)&lt;/li&gt;
  &lt;li&gt;Lives in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ipc/ipdl/ipdl.py&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Not great fun to work with, infrequently modified&lt;/li&gt;
      &lt;li&gt;C++ code goes to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$OBJDIR/ipc/ipdl&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;C++ headers to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$OBJDIR/ipc/ipdl/_ipdlheaders&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Headers organized by C++ namespace&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;webidl&quot;&gt;WebIDL&lt;/h3&gt;

&lt;p&gt;TODO&lt;/p&gt;

&lt;h2 id=&quot;memory-management&quot;&gt;Memory Management&lt;/h2&gt;

&lt;p&gt;Owned pointers&lt;/p&gt;

&lt;p&gt;std::unique_ptr - encapsulates lots of details of passing ownership of pointers around (for exclusive-ownership)&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Not available because not all our platforms support it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But we do have Mozilla::UniquePtr (in mfbt)&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Same interface as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::unique_ptr&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Anywhere you might need to pass raw pointers around, use UniquePtr instead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The old way: (gone from Gecko as of 2021, it seems)&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsAutoPtr&amp;lt;T&amp;gt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsAutoArrayPtr&amp;lt;T&amp;gt;&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::auto_ptr&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;auto_ptr&lt;/code&gt;, these are deprecated too&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shared pointers&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;We do this by reference counting&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AddRef()&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Release()&lt;/code&gt; methods
    &lt;ul&gt;
      &lt;li&gt;Doesn’t matter virtualness or not&lt;/li&gt;
      &lt;li&gt;You just need the names and parameters, if any&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Unlike &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::shared_ptr&lt;/code&gt;, which manages proxies to objects, in Gecko, objects manage their own refcounts directly&lt;/li&gt;
  &lt;li&gt;If you just want to pass around shared data, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::shared_ptr&lt;/code&gt; is easier&lt;/li&gt;
  &lt;li&gt;For Gecko, we control all the data, so we just manage refcount directly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reference counting: thread safety&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Thread safety: thread-safe and non-threadsafe options are supported&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::shared_ptr&lt;/code&gt; only available in thread-safe version&lt;/li&gt;
  &lt;li&gt;If you’re passing objects among threads, please use thread-safe refcounting&lt;/li&gt;
  &lt;li&gt;DEBUG builds verify thread usage by:
    &lt;ul&gt;
      &lt;li&gt;marking the owning thread that allocates the object using nonsafe reference counting&lt;/li&gt;
      &lt;li&gt;all future refcount operations will check if they are on the owning thread, and crash if not&lt;/li&gt;
      &lt;li&gt;else, bad things may happen in non-debug builds&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Smart pointers&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Used to avoid needing to manually call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AddRef()&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Release()&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RefPtr&amp;lt;T&amp;gt;&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;found in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/mfbt&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Used for concrete classes&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsCOMPtr&amp;lt;T&amp;gt;&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Very old, XPCOM smart pointer&lt;/li&gt;
      &lt;li&gt;Used with interface classes: XPIDL, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsI*&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Cooperates with many other things
        &lt;ul&gt;
          &lt;li&gt;Lots of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_Thing&lt;/code&gt; helpers&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cycles&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Reference counting is not perfect&lt;/li&gt;
  &lt;li&gt;Easy to create cyclic references =&amp;gt; memory leaks&lt;/li&gt;
  &lt;li&gt;Not just C++ &amp;lt;=&amp;gt; C++ cycles, either.
    &lt;ul&gt;
      &lt;li&gt;Cycles can include JS objects!&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Avoiding this: we tried avoiding cycles, using raw pointers (scary)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Refcounting: Cycle Collector&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Rather than manually break cycles, periodically detect &amp;amp; collect cycles
    &lt;ul&gt;
      &lt;li&gt;Integration with JS GC to trigger this&lt;/li&gt;
      &lt;li&gt;JS GC triggers things, then cycle collector looks for cycles&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;If an object participates in cycle collection, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AddRef()&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Release()&lt;/code&gt; do extra work to notify cycle collector&lt;/li&gt;
  &lt;li&gt;Generally only for DOM things (not network or gfx)&lt;/li&gt;
  &lt;li&gt;Lots of obtuse macros for making this almost-nice&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Refcounting: declaration&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Macros handle lots of this&lt;/li&gt;
  &lt;li&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsISupports&lt;/code&gt; things (anything with XPIDL associated to it):
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_DECL_ISUPPORTS&lt;/code&gt; single-threaded&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_DECL_THREADSAFE_ISUPPORTS&lt;/code&gt; thread-safe&lt;/li&gt;
      &lt;li&gt;Drop these macros in your class declaration&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Refcounting: definition&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;In concrete &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsThing.cpp&lt;/code&gt;, list concrete classname and list of implemented interfaces
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_IMPL_SUPPORTS(nsThing, nsIThing, ...);&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Same syntax for thread-safe and non-thread-safe classes&lt;/li&gt;
  &lt;li&gt;For non-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsISupports&lt;/code&gt; things:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_INLINE_DECL_REFCOUNTING&lt;/code&gt; single-threaded&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NS_INLINE_DECL_THREADSAFE_REFCOUNTING&lt;/code&gt; multi-threaded&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Refcounting: implementation&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Generally, the macros provide all you’ll need&lt;/li&gt;
  &lt;li&gt;See &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xpcom/glue/nsISupportsImpl.h&lt;/code&gt; for the grotty details&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Leak Checking&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;DEBUG only&lt;/li&gt;
  &lt;li&gt;We have leak checking tooling for refcounted things&lt;/li&gt;
  &lt;li&gt;Not as complete as Valgrind / Asan&lt;/li&gt;
  &lt;li&gt;Refcounted classes are automatically leak checked&lt;/li&gt;
  &lt;li&gt;Individual &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new&lt;/code&gt; isn’t counted
    &lt;ul&gt;
      &lt;li&gt;ASan / Valgrind test runs to check leaks, but totally separate from our debug builds&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Leak Checking: macros&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Also possible to leak check non-reference counted classes&lt;/li&gt;
  &lt;li&gt;Helpful to ensure new code manages memory correctly&lt;/li&gt;
  &lt;li&gt;Include reference to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MOZ_COUNT_CTOR(klassname)&lt;/code&gt; in all constructors&lt;/li&gt;
  &lt;li&gt;In destructor, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MOZ_COUNT_DTOR(klassname)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Limitations:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Checking hierarchies is difficult
    &lt;ul&gt;
      &lt;li&gt;We generally avoid hierarchies in Gecko&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MOZ_COUNT_CTOR_INHERITED&lt;/code&gt; is available, but rarely used&lt;/li&gt;
      &lt;li&gt;Generally just use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MOZ_COUNT_CTOR&lt;/code&gt; in the base class&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Checking templates classes is difficult
    &lt;ul&gt;
      &lt;li&gt;Solution: use a non-templated base class&lt;/li&gt;
      &lt;li&gt;Same approach as inherited / hierarchies&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More info:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;BloatView, MDN article (RIP TODO find this)
    &lt;ul&gt;
      &lt;li&gt;Runs on DEBUG tests by default&lt;/li&gt;
      &lt;li&gt;Also has info on leaks not reproducible locally&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Refcounting: ownership transfers&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Want to avoid passing raw pointers to refcounted classes&lt;/li&gt;
  &lt;li&gt;You have a smart pointer to some class, allocate it, do stuff with it&lt;/li&gt;
  &lt;li&gt;How do you get a pointer to that object out of your method?&lt;/li&gt;
  &lt;li&gt;Can’t just return the raw pointer: the ref will get released, you’ll be passing a pointer to freed memory 🙀&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ownership transfer strategies&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;As usual with Gecko, there are many ways to do it&lt;/li&gt;
  &lt;li&gt;Oldest: outparam &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T**&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Some class returns a pointer to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T*&lt;/code&gt;, so, class pointer pointer&lt;/li&gt;
      &lt;li&gt;Common with XPIDL-style interfaces&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;More common on C++ side: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;already_AddRefed&amp;lt;T&amp;gt;&lt;/code&gt; return value
    &lt;ul&gt;
      &lt;li&gt;Generally indicates new object entirely yours&lt;/li&gt;
      &lt;li&gt;Means: I’m giving you a pointer that has had &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AddRef()&lt;/code&gt; called on it&lt;/li&gt;
      &lt;li&gt;Typically used in create interfaces as a return value&lt;/li&gt;
      &lt;li&gt;Means also: need to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Release()&lt;/code&gt; it at some point&lt;/li&gt;
      &lt;li&gt;Can’t do much with it except assign it to a smart pointer&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;“Modern” way: return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RefPtr&amp;lt;T&amp;gt;&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsCOMPtr&amp;lt;T&amp;gt;&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Pass around or return smart pointers themselves&lt;/li&gt;
      &lt;li&gt;With recent C++ standard changes, now actually efficient
        &lt;ul&gt;
          &lt;li&gt;In the past, might or might not be efficient&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Not currently super safe with our current smart pointer implementation with current compilers&lt;/li&gt;
      &lt;li&gt;Planning to make improvements&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ownership transfers: summary table&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;Pointer outparam&lt;/th&gt;
      &lt;th&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;already_AddRefed&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/th&gt;
      &lt;th&gt;Smart pointer&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Identifying feature&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T**&lt;/code&gt; argument (usually last in args list, in XPIDL)&lt;/td&gt;
      &lt;td&gt;return type&lt;/td&gt;
      &lt;td&gt;return type&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Passing ownership from a smart pointer&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p.forget(outparam);&lt;/code&gt; (stores the wrapped pointer into the outparam)&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return p.forget();&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return p;&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Caller (Starting with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RefPtr &amp;lt;T&amp;gt; p;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;o-&amp;gt;Method(getter_AddRefs(p));&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p = o-&amp;gt;Method();&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p = o-&amp;gt;Method();&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Use cases&lt;/td&gt;
      &lt;td&gt;XPIDL-style interfaces, especially for helper methods called by XPIDL methods&lt;/td&gt;
      &lt;td&gt;static &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Create()&lt;/code&gt; methods&lt;/td&gt;
      &lt;td&gt;many&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;QueryInterface: XPCOM’s dynamic_cast&lt;/p&gt;

&lt;p&gt;Next couple sections: brief digression into nuts &amp;amp; bolts of XPIDL, XPCOM&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Every class/interface in Gecko gets a UUID
    &lt;ul&gt;
      &lt;li&gt;tied specifically to the interface&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Given a random pointer, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsISupports&lt;/code&gt; pointer&lt;/li&gt;
  &lt;li&gt;Can check if the pointer supports a given interface by passing it a UUID&lt;/li&gt;
  &lt;li&gt;We have infrastructure to simplify these checks&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;do_queryinterface&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_QueryInterface()&lt;/code&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Given pointer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsCOMPtr&amp;lt;nsIFoo&amp;gt; foo&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;If you want to know if it supports &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsIBar&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Just do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsCOMPtr&amp;lt;nsIBar&amp;gt; bar = do_QueryInterface(foo);&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bar&lt;/code&gt; will be non-null if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt; was non-null and supports &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsIBar&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Handles null-checking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt;, looking up interface UUID for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsIBar&lt;/code&gt;, looking up list of interface UUIDs supported by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Because QI does the null-check for you, you can QI through multiple interfaces and only null-check once at the end.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;do_createinstance&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_CreateInstance()&lt;/code&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Used for creating objects across C++ and JS (for XPIDL)&lt;/li&gt;
  &lt;li&gt;Because we don’t use exceptions in C++, the constructor cannot return an error&lt;/li&gt;
  &lt;li&gt;So, we construct a minimal object, then call an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init()&lt;/code&gt; method to finish initializing&lt;/li&gt;
  &lt;li&gt;To avoid using UUIDs, we have a thing called “contract ID” (typically defined in IDL)
    &lt;ul&gt;
      &lt;li&gt;Example: “@mozilla.org/foo;1”.&lt;/li&gt;
      &lt;li&gt;Stays the same even if the interface changes (hence, the UUID must be updated)&lt;/li&gt;
      &lt;li&gt;Reduces churn due to UUID evolution / interface evolution&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Syntax enforces creation/initialization separation
    &lt;ul&gt;
      &lt;li&gt;Makes it easy to get &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ns_result&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init()&lt;/code&gt; and relay to JS as a JS Exception&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;C++ syntax:
    &lt;ul&gt;
      &lt;li&gt;construction: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsCOMPtr&amp;lt;nsIFoo&amp;gt; f = do_CreateInstance(&quot;@mozilla.org/foo;1&quot;);&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;initialization: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsresult rv = f-&amp;gt;init();&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;JS syntax:
    &lt;ul&gt;
      &lt;li&gt;construction: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let f = Cc[&quot;@mozilla.org/foo;1&quot;].createInstance(nsIFoo);&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;initialization: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f.init();&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;On the C++ side, typically better to just directly init via the constructor, instead of doing all this indirection&lt;/li&gt;
  &lt;li&gt;On the JS side, this machinery is unavoidable, so these patterns are necessary&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;do_getservice&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_GetService()&lt;/code&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Services are XPCOM’s singletons&lt;/li&gt;
  &lt;li&gt;They are lazily created by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_GetService()&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Enforced only by convention: if you &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_CreateInstance&lt;/code&gt; instead, strange things may happen
    &lt;ul&gt;
      &lt;li&gt;Weirdness is especially likely if you &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_CreateInstance&lt;/code&gt; more than once&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_GetService&lt;/code&gt; is prohibitively slow for common services&lt;/li&gt;
  &lt;li&gt;Instead, we have a faster way to get common services: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;services::&lt;/code&gt; (aka Services.jsm on JS side)
    &lt;ul&gt;
      &lt;li&gt;defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xpcom/build/ServiceList.h&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Syntax examples:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_GetService&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsCOMPtr&amp;lt;nsICatchyService&amp;gt; service = do_GetService(&quot;@mozilla.org/catchy;1&quot;);&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;faster &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;services&lt;/code&gt; global: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsCOMPtr&amp;lt;nsICatchyService&amp;gt; service = services::GetCatchyService();&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;do_getinterface&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_GetInterface()&lt;/code&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Was meant to replace attribute access&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsIInterfaceRequestor&lt;/code&gt; is a fairly common interface&lt;/li&gt;
  &lt;li&gt;Used to ask an object if it has something corresponding to some interface UUID&lt;/li&gt;
  &lt;li&gt;Could return anything that conforms to the UUID:
    &lt;ul&gt;
      &lt;li&gt;might return a direct member of the concrete class&lt;/li&gt;
      &lt;li&gt;or the class itself&lt;/li&gt;
      &lt;li&gt;or something else entirely that happens to implement that interface UUID among many others&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;This is not a good pattern
    &lt;ul&gt;
      &lt;li&gt;e.g. browser code will QI to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsIInterfaceRequestor&lt;/code&gt;,&lt;/li&gt;
      &lt;li&gt;then get some interface,&lt;/li&gt;
      &lt;li&gt;then query that interface to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsIInterfaceRequestor&lt;/code&gt;, etc.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Long, ugly chain of operations to do something relatively simple&lt;/li&gt;
  &lt;li&gt;To make matters worse, it’s not always clear if you should &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_GetInterface&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QueryInterface&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Don’t use this in new code.&lt;/li&gt;
  &lt;li&gt;Instead, just provide an attribute or method to access a concrete thing, and sidestep the UUID machinery
    &lt;ul&gt;
      &lt;li&gt;Example: given &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsCOMPtr&amp;lt;nsIFoo&amp;gt; foo&lt;/code&gt;. How to get an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsIBar&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt;?
        &lt;ol&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsCOMPtr&amp;lt;nsIInterfaceRequestor&amp;gt; iir = do_QueryInterface(foo);&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsComPtr&amp;lt;nsIBar&amp;gt; bar = do_GetInterface(iir);&lt;/code&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bar&lt;/code&gt; is non-null if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt; was non-null and supported &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsIInterfaceRequestor&lt;/code&gt; and knew how to provide &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsIBar&lt;/code&gt; things&lt;/li&gt;
      &lt;li&gt;null-check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bar&lt;/code&gt; just once at the end and you’re done&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Again: you may see this, but don’t use it in new code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few final bits still need to be copied over from my paper notes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Gecko C++ Data Structures
    &lt;ul&gt;
      &lt;li&gt;XPCOM / MFBT Data Structures: Growable vectors, hashtables, lists, strings, string helpers&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;NSPR logging&lt;/li&gt;
  &lt;li&gt;Debugging: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./mach run&lt;/code&gt;, rr (time-traveling record replay debugger, linux only)&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 10 Dec 2021 23:42:55 +0000</pubDate>
        <link>https://6a68.net/2021/gecko-cpp/</link>
        <guid isPermaLink="true">https://6a68.net/2021/gecko-cpp/</guid>
        
        
        <category>mozilla</category>
        
        <category>c++</category>
        
        <category>gecko</category>
        
      </item>
    
      <item>
        <title>Test Pilot in 2018: Lessons Learned from Screenshots</title>
        <description>&lt;h2 id=&quot;test-pilot-in-2018-lessons-learned-from-graduating-screenshots-into-firefox&quot;&gt;Test Pilot in 2018: Lessons learned from graduating Screenshots into Firefox&lt;/h2&gt;

&lt;p&gt;Wil and I were talking about the Bugzilla vs Github question for Screenshots a couple of days ago, and I have to admit that I’ve come around to “let’s just use Bugzilla for everything, and just ride the trains, and work with the existing processes as much as possible.”&lt;/p&gt;

&lt;p&gt;I think it’s important to point out that this is a complete departure from my original point of view. Getting an inside view of how and why Firefox works the way it does has changed my mind. Everything just moves slower, with so many good reasons for doing so (good topic for another blog post). Given that our goal is to hand Screenshots off, just going with the existing processes, minimizing friction, is the way to go.&lt;/p&gt;

&lt;p&gt;If Test Pilot’s goals include landing stuff in Firefox, what does this mean for the way that we run earlier steps in the product development process?&lt;/p&gt;

&lt;h2 id=&quot;suggestions-for-experiments-that-the-test-pilot-team-will-graduate-into-firefox&quot;&gt;Suggestions for experiments that the Test Pilot team will graduate into Firefox&lt;/h2&gt;

&lt;h3 id=&quot;ship-maximal-not-minimal-features&quot;&gt;Ship maximal, not minimal, features&lt;/h3&gt;

&lt;p&gt;I don’t think we should plan on meaningful iteration once a feature lands in Firefox. It’s just fundamentally too slow to iterate rapidly, and it’s way too hard for a very small team to ship features faster than that default speed (again, many good reasons for that friction).&lt;/p&gt;

&lt;p&gt;The next time we graduate something into Firefox, we should plan to ship much more than a minimum viable product, because we likely won’t get far past that initial landing point.&lt;/p&gt;

&lt;h3 id=&quot;when-in-firefox-embrace-the-firefox-ways&quot;&gt;When in Firefox, embrace the Firefox ways&lt;/h3&gt;

&lt;p&gt;Everything we do, once an experiment gets approval to graduate, should be totally Firefox-centric. Move to Bugzilla for bugs (except, maybe, for server bugs). Mozilla-central for code, starting with one huge import from Github (again, except for server code). Git-cinnabar works really well, if you prefer git over mercurial. We have committers within the team now, and relationships with reviewers, so the code side of things is pretty well sorted.&lt;/p&gt;

&lt;p&gt;Similarly for processes: we should just go with the existing processes to the best of our ability, which is to say, constantly ask the gatekeepers if we’re doing it right. Embrace the fact that everything in Firefox is high-touch, and use existing personal relationships to ask early and often if we’ve missed any important steps. We will always miss something, whether it’s new rules for some step, or neglecting to get signoff from some newly-created team, but we can plan for that in the schedule. I think we’ve hit most of the big surprises in shipping Screenshots.&lt;/p&gt;

&lt;h3 id=&quot;aim-for-bigger-audiences-in-test-pilot&quot;&gt;Aim for bigger audiences in Test Pilot&lt;/h3&gt;

&lt;p&gt;Because it’s difficult to iterate on features when code is inside Firefox, we should make our Test Pilot audience as close to a release audience as possible. We want to aim for the everyday users, not the early adopters. I think we can do this by just advertising Test Pilot experiments more heavily.&lt;/p&gt;

&lt;p&gt;By gathering data from a larger audience, our data will be more representative of the release audience, and give us a better chance of feature success.&lt;/p&gt;

&lt;h3 id=&quot;aim-for-web-flavored-features--avoid-dramatic-changes-to-the-firefox-ui&quot;&gt;Aim for web-flavored features / avoid dramatic changes to the Firefox UI&lt;/h3&gt;

&lt;p&gt;Speaking as the person who did “the weird Gecko stuff” on both Universal Search and Min-Vid, doing novel things with the current Firefox UI is hard, for all the reasons Firefox things are hard: the learning curve is significant and it’s high-touch. Knowledge of how the code works is confined to a small group of people, the docs aren’t great, and learning how things work requires reading the source code, plus asking for help on IRC.&lt;/p&gt;

&lt;p&gt;Given that our team’s strengths lie in web development, we will be more successful if our features focus on the webby things: cross-device, mobile, or cloud integration; bringing the ‘best of the web’ into the browser. This is stuff we’re already good at, stuff that could be a differentiator for Firefox just as much as new Firefox UI, and we can iterate much more quickly on server code.&lt;/p&gt;

&lt;p&gt;This said, if Firefox Product wants to reshape the browser UI itself in powerful, unexpected, novel ways, we can do it, but we should have some Firefox or Platform devs committed to the team for a given experiment.&lt;/p&gt;

</description>
        <pubDate>Sat, 09 Dec 2017 00:36:00 +0000</pubDate>
        <link>https://6a68.net/2017/bugzilla-github-and-graduating-into-firefox/</link>
        <guid isPermaLink="true">https://6a68.net/2017/bugzilla-github-and-graduating-into-firefox/</guid>
        
        
        <category>mozilla</category>
        
        <category>test-pilot</category>
        
        <category>screenshots</category>
        
      </item>
    
      <item>
        <title>Bootstrapping Test Pilot Community through Public Decision Making</title>
        <description>&lt;p&gt;This proposal is pulled verbatim from &lt;a href=&quot;https://mail.mozilla.org/pipermail/testpilot-dev/2016-October/000275.html&quot;&gt;a message&lt;/a&gt; I sent to the Test Pilot mailing list a few minutes ago.&lt;/p&gt;

&lt;p&gt;The question is: how do we best begin to build a community around Test Pilot?&lt;/p&gt;

&lt;p&gt;My answer: start by making decisions in public.&lt;/p&gt;

&lt;p&gt;If this seems interesting to you, read on below.&lt;/p&gt;

&lt;h2 id=&quot;proposed-participation-timeline&quot;&gt;Proposed Participation Timeline&lt;/h2&gt;

&lt;p&gt;Q4 2016: Start by making decisions in public, in the Discourse user forums.&lt;/p&gt;

&lt;p&gt;Q4 2016 - Q1 2017: Once we’ve made our process accessible to contributors, ask active Mozillians to get involved. Build an awesome core community. Advertise idea submissions to active Mozillians &amp;amp; iterate on the submission system before a huge public influx.&lt;/p&gt;

&lt;p&gt;Q1-Q2 2017: Once the core community is in place, and idea submission has been tweaked, get Marketing involved with a public call for ideas. Our awesome core community will help manage the influx: greet newcomers, bash trolls, de-dupe suggestions.&lt;/p&gt;

&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;

&lt;p&gt;To frame the discussion, I wrote up some &lt;a href=&quot;http://6a68.net/2016/open-product-development/&quot;&gt;thoughts&lt;/a&gt; on what a more open, community-centered product development cycle might look like. TL;DR: give community a seat at the table by offering equal visibility into the process, and opportunities to provide input at decision points.&lt;/p&gt;

&lt;p&gt;See also &lt;a href=&quot;http://producingoss.com/en/producingoss.html#avoid-private-discussions&quot;&gt;Producing OSS&lt;/a&gt;, which makes interesting points on the importance of public decision-making.&lt;/p&gt;

&lt;h2 id=&quot;suggested-q4-plan&quot;&gt;Suggested Q4 plan&lt;/h2&gt;

&lt;p&gt;In Q4, we can set the stage for community by making our work public:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ask product and UX to move decision making discussions to Discourse&lt;/li&gt;
  &lt;li&gt;ask experiment teams to post in Discourse as they launch, measure, iterate, and wind down&lt;/li&gt;
  &lt;li&gt;make Discourse a secondary call to action on the Test Pilot experiment pages&lt;/li&gt;
  &lt;li&gt;deprecate mailing list in favor of Discourse&lt;/li&gt;
  &lt;li&gt;(if there’s time) ask vetted, active Mozillians to join the conversation&lt;/li&gt;
  &lt;li&gt;(if there’s time) ask Mozillians to share ideas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we make these changes in Q4, then by Q1, we’ll have plenty of content in Discourse. New community members will tend to model their input on the tone and content of the existing discussion; for this reason, I think we should hold the open call until a bit later. I realize I’m contradicting my own recent suggestion, but I do think this approach will yield better results.&lt;/p&gt;

&lt;h2 id=&quot;key-result-100-monthly-active-discourse-users&quot;&gt;Key Result: 100 monthly active Discourse users&lt;/h2&gt;

&lt;p&gt;One natural number to measure would be the number of monthly active Discourse users (MADU), meaning: users who post at least once a month in the Test Pilot category. Right now, this number is probably below 10. If all the dev teams and product/UX get involved, that’ll jump to, maybe, 30 MADUs. If we get Mozillians engaged, we could see this number jump into the hundreds. 100 MADUs seems ambitious, but possible.&lt;/p&gt;

&lt;h2 id=&quot;q4-plan-in-detail&quot;&gt;Q4 plan in detail&lt;/h2&gt;

&lt;p&gt;It’s a bit buried in the list above, but I think we should deprecate the mailing list, and move discussion to Discourse instead. Our current list has little traffic, and a primitive, plain text archive that doesn’t allow search. It would be easy to move the current traffic to Discourse. Finally, moving to Discourse would encourage the Test Pilot team to use it.&lt;/p&gt;

&lt;p&gt;Going into a bit more detail on the types of content that should move to Discourse to help seed our community:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design phase (product / UX):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Idea proposals &amp;amp; discussion&lt;/li&gt;
  &lt;li&gt;Decision making discussions: which ideas to invest in, and why those ideas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Development / iteration phase (product / UX / dev):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Summaries of user interaction data (how are people using the product, how many keep using it)&lt;/li&gt;
  &lt;li&gt;High level discussion of which features to add, change, or remove, grounded in the public interaction data&lt;/li&gt;
  &lt;li&gt;I’m not yet sure how much development discussion should happen on Discourse vs. a specific mailing list; we can ask around to see what approaches different teams would like to try.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Graduation / end of cycle phase (product):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Discussions about whether to keep an experiment running, move into Firefox, or retire it.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h1&gt;

&lt;p&gt;That does it for the mailing list post.&lt;/p&gt;

&lt;p&gt;What do you think about this proposal? Is this a good way to build the foundations of a participatory Test Pilot community?&lt;/p&gt;

&lt;p&gt;Let me know! Twitter and email are in the footer below.&lt;/p&gt;
</description>
        <pubDate>Wed, 05 Oct 2016 19:30:00 +0000</pubDate>
        <link>https://6a68.net/2016/public-decision-making/</link>
        <guid isPermaLink="true">https://6a68.net/2016/public-decision-making/</guid>
        
        
        <category>mozilla</category>
        
        <category>test-pilot</category>
        
      </item>
    
      <item>
        <title>Test Pilot and Open Product Development</title>
        <description>&lt;p&gt;Test Pilot started out as a better way for Mozilla to build ambitious new features in Firefox: prototype features as add-ons, share with an opt-in beta testing community, and iterate much more quickly than the Firefox release cycle allows. This all makes sense, and it’s amazing how much we’ve accomplished in just over a year–but this conception leaves out the community algother.&lt;/p&gt;

&lt;p&gt;How could Test Pilot be more open, more participatory?&lt;/p&gt;

&lt;p&gt;Well, what if the Test Pilot team asked the community for feature ideas?&lt;/p&gt;

&lt;p&gt;Even better: what if Test Pilot shipped prototypes built by self-organized teams of community members (volunteer or staff)?&lt;/p&gt;

&lt;p&gt;What if we think about Test Pilot as &lt;em&gt;a community of contributors interested in discussing and building new Firefox features&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;Yeah, that’s the stuff!&lt;/p&gt;

&lt;p&gt;I don’t have the time or space to get deeper into this vision right now, but I will mention it in another post, soon.&lt;/p&gt;

&lt;p&gt;Assuming it makes sense to build products in the open from the early stages, how might we get there?&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Here’s a rough sketch of an open product development lifecycle for Firefox features, centered around Test Pilot.&lt;/p&gt;

&lt;h3 id=&quot;generating-and-discussing-feature-ideas&quot;&gt;Generating and discussing feature ideas&lt;/h3&gt;
&lt;p&gt;An inventor with an idea creates a Discourse account and creates a post describing their idea. This could be anyone: a product manager at Mozilla, or a new Mozillian located anywhere in the world.&lt;/p&gt;

&lt;p&gt;Interested community members discuss the idea, and help the inventor improve their proposal.&lt;/p&gt;

&lt;p&gt;Community members with user research skills can help generate qualitative or quantitative insights about ideas they are interested in.&lt;/p&gt;

&lt;h3 id=&quot;turning-ideas-into-working-prototypes&quot;&gt;Turning ideas into working prototypes&lt;/h3&gt;
&lt;p&gt;Community members with design and development skills self-organize to build prototypes of ideas they believe in.&lt;/p&gt;

&lt;p&gt;Companies (like Mozilla) can sponsor development of ideas.&lt;/p&gt;

&lt;h3 id=&quot;deciding-which-prototypes-belong-in-firefox-test-pilot&quot;&gt;Deciding which prototypes belong in Firefox Test Pilot&lt;/h3&gt;
&lt;p&gt;Every few months, someone from the Firefox product org leads a public discussion about which of the in-progress prototypes might be a good fit for the Firefox roadmap.&lt;/p&gt;

&lt;p&gt;The decision-making process is a public, open conversation based on publicly defined criteria (the public Firefox roadmap and Mozilla’s guiding principles).&lt;/p&gt;

&lt;p&gt;Input from the community is welcome, the Firefox product org makes the final decision, and deliberations happen in the same public channels used by the rest of the community.&lt;/p&gt;

&lt;h3 id=&quot;sharing-prototypes-with-the-firefox-test-pilot-audience&quot;&gt;Sharing prototypes with the Firefox Test Pilot audience&lt;/h3&gt;
&lt;p&gt;This is the part we’ve already built at &lt;a href=&quot;https://testpilot.firefox.com&quot;&gt;https://testpilot.firefox.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Prototypes ship in the Test Pilot site, and Mozilla provides marketing support and a global audience. Firefox users interested in trying new features install different prototypes, and offer feedback on what they do or don’t like.&lt;/p&gt;

&lt;h3 id=&quot;sharing-prototypes-that-dont-make-it-into-test-pilot&quot;&gt;Sharing prototypes that don’t make it into Test Pilot&lt;/h3&gt;
&lt;p&gt;Like any other Firefox add-on, teams ship in AMO (or self-host) and self-promote.&lt;/p&gt;

&lt;p&gt;It’s still possible to create a great feature that later makes it into Test Pilot, or becomes a great add-on on its own, and teams can continue to discuss features and updates with the Test Pilot community.&lt;/p&gt;

&lt;h3 id=&quot;iterating-on-the-product-concept&quot;&gt;Iterating on the product concept&lt;/h3&gt;
&lt;p&gt;Once launched in Test Pilot, the product should evolve based on quantitative usage data, as well as qualitative user feedback.&lt;/p&gt;

&lt;p&gt;Prototype building teams are encouraged to make their discussions public, so that interested community members can provide input.&lt;/p&gt;

&lt;h3 id=&quot;from-test-pilot-prototype-to-firefox&quot;&gt;From Test Pilot prototype to Firefox&lt;/h3&gt;
&lt;p&gt;The Firefox product org decides which Test Pilot experiments to turn into real browser features. Again, this is an open discussion, centered around criteria any contributor could understand (except for contractual / partner private factors).&lt;/p&gt;

&lt;h3 id=&quot;from-test-pilot-prototype-to-amo&quot;&gt;From Test Pilot prototype to AMO&lt;/h3&gt;
&lt;p&gt;Ideas that fail to catch on with a big audience, at the end of their Test Pilot run, can still be supported by the original team, or handed off to other community members, and permanently hosted on AMO.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Next steps: I’m out of time for now, but I’d like to explore which parts of this theoretical open product dev cycle might make sense at Mozilla. In other words, stay tuned, more to come :-)&lt;/p&gt;

&lt;p&gt;What do you think? Let me know! Twitter and email are in the footer below.&lt;/p&gt;
</description>
        <pubDate>Wed, 05 Oct 2016 00:36:00 +0000</pubDate>
        <link>https://6a68.net/2016/open-product-development/</link>
        <guid isPermaLink="true">https://6a68.net/2016/open-product-development/</guid>
        
        
        <category>mozilla</category>
        
        <category>test-pilot</category>
        
      </item>
    
      <item>
        <title>The Joy of the Hack: Gecko Focus Stealing Edition</title>
        <description>&lt;p&gt;I’ve been working on a prototype, on and off, over the past year. The idea 
is to do cool new stuff with the little popup menu that appears below the
Firefox address bar as you type into it:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.dropbox.com/s/94876wh1g3042ik/Screen%20Shot%202016-03-31%20at%206.01.16%20PM.png?dl=0&amp;amp;raw=true&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This prototype will be available to a beta testing audience as part of the
new Test Pilot program at Mozilla, which is slated to launch in May. See
the links section at the end of this article for more about Test Pilot.&lt;/p&gt;

&lt;p&gt;There are lots of experiments we’d like to try with the urlbar, but the first one shows
a server-generated recommendation above the existing history items and search suggestions.
Because this is just a prototype, we want to get as much quality as we can with as
little work as possible–which means we’re relying heavily on third-party services.&lt;/p&gt;

&lt;p&gt;The recommendation is generated by a really simple algorithm:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;You type something in the urlbar, like ‘lol wut p’, and the keystrokes are sent to a server.&lt;/li&gt;
  &lt;li&gt;The server looks up search suggestions for ‘lol wut p’, and finds that the top suggestion is ‘lol wut pear’.&lt;/li&gt;
  &lt;li&gt;The server sends the suggestion, ‘lol wut pear’, to a search engine service; the top result is a page about that meme.&lt;/li&gt;
  &lt;li&gt;The top result is sent back to the browser, where it’s shown in the urlbar popup:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;https://www.dropbox.com/s/z7mr6lz2iov7nwa/Screen%20Shot%202016-03-31%20at%203.49.14%20PM.png?dl=0&amp;amp;raw=true&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;interacting-with-the-popup&quot;&gt;Interacting with the popup&lt;/h4&gt;

&lt;p&gt;Keyboard interactions with the popup are straightforward.
The list of results can be traversed using the up and down keys; a blue
highlight tells the user which item is currently selected. Hitting ‘Enter’ loads 
the URL of the highlighted item.&lt;/p&gt;

&lt;p&gt;If none of the results are highlighted when the user hits ‘Enter’, the browser either
surfs to the URL in the urlbar, or searches the default search engine for the
string in the urlbar. To clarify this search-or-navigate behavior, a top row
was recently added to the urlbar, highlighted by default, which explains the
options visually:&lt;/p&gt;

&lt;p&gt;If the urlbar contents look like a URL, the top row explains that you’ll visit that URL by hitting Enter:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.dropbox.com/s/i0mrr4hgu0qm7uj/Screen%20Shot%202016-03-31%20at%208.58.03%20PM.png?dl=0&amp;amp;raw=true&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Otherwise, the top row explains that you’ll search for the typed string by hitting Enter:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.dropbox.com/s/gj00jtx4lxl5eeb/Screen%20Shot%202016-03-31%20at%208.57.45%20PM.png?dl=0&amp;amp;raw=true&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;fitting-the-recommendation-into-the-existing-interface&quot;&gt;Fitting the recommendation into the existing interface&lt;/h4&gt;

&lt;p&gt;Due to technical constraints, we’re inserting our recommendation above the existing list of results.
Rather than continue to highlight the top results row, it seemed best to remove the highlight
completely.&lt;/p&gt;

&lt;p&gt;This initially seemed like a pretty simple task: the highlight is set by adjusting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selectedIndex&lt;/code&gt;
property on the panel, and setting it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-1&lt;/code&gt; removes the highlight completely, so the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stealHighlight&lt;/code&gt; function initially might look something like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;function stealHighlight() {
  gURLBar.popup.selectedIndex = -1;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sadly, this approach doesn’t work:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;https://www.youtube.com/embed/kKVzIGi8Nuk&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;The results list is stealing the highlight back! What’s going on?&lt;/p&gt;

&lt;p&gt;It turns out that the list of results isn’t rendered all at once. To keep the urlbar
responsive to additional keystrokes or other user input, the results list is rendered
a little at a time, in chunks of 5 rows, up to 6 times, for a total of 30 results in
a scrollable list.&lt;/p&gt;

&lt;p&gt;In addition, each time a new set of rows is inserted, the highlight is reapplied to
the selected item in the popup. This is why naively unsetting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selectedIndex&lt;/code&gt; didn’t
work: the recommendation finishes rendering before the results list, so the
highlight is quickly stolen back.&lt;/p&gt;

&lt;p&gt;What to do?&lt;/p&gt;

&lt;p&gt;There are two problems to be solved: detecting when new results are inserted,
and stealing the highlight back quickly.&lt;/p&gt;

&lt;h4 id=&quot;detecting-when-results-are-inserted&quot;&gt;Detecting when results are inserted&lt;/h4&gt;

&lt;p&gt;The first problem, detecting when results are inserted, was a tough one. The
UI controller code that fetches and inserts results is written in C++ (ugh),
and there’s really no way to break into that code from an add-on. The C++
controller code is &lt;a href=&quot;https://dxr.mozilla.org/mozilla-central/source/toolkit/components/autocomplete/nsAutoCompleteController.cpp&quot;&gt;a huge file&lt;/a&gt;, so although Gecko’s XPCOM component system does
allow components to be written in JS or C++, porting all of its behavior to JS would
have required a rewrite–not a viable option. The existing
code also doesn’t fire any signals that could be used to detect when
results are about to be inserted.&lt;/p&gt;

&lt;p&gt;The only option I could come up with was to use a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MutationObserver&lt;/code&gt;
(&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver&quot;&gt;MDN&lt;/a&gt;) to listen
for changes in the popup’s XUL DOM when the results were inserted. Even this required
some care: the results list recycles DOM nodes as a
performance enhancement, so listening for changes in the popup’s
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;childList&lt;/code&gt; wasn’t enough. Happily, XUL elements store visible data in attributes,
as you can see in this example of a typical result:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;richlistitem
  xmlns=&quot;http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul&quot;
  url=&quot;https://www.bing.com/search?q=lol+wut&amp;amp;amp;pc=MOZI&quot;
  title=&quot;lol wut - Bing&quot;
  type=&quot;favicon&quot;
  text=&quot;lol wut p&quot;
  class=&quot;autocomplete-richlistitem&quot;
  image=&quot;moz-anno:favicon:https://www.bing.com/s/a/bing_p.ico&quot;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When a result row is reused, its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;url&lt;/code&gt; attribute is changed to reflect the
new result’s URL, and attribute changes are visible to MutationObservers.
Ultimately, listening for changes on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;url&lt;/code&gt; attribute, along with
changes in the number of child elements of the popup, led to fairly reliable signals.&lt;/p&gt;

&lt;h4 id=&quot;quickly-stealing-the-highlight&quot;&gt;Quickly stealing the highlight&lt;/h4&gt;

&lt;p&gt;The second problem, stealing the highlight quickly enough to prevent flickering,
was a challenge.&lt;/p&gt;

&lt;p&gt;We could try using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTimeout&lt;/code&gt; ourselves, to steal the highlight on a later turn,
but this doesn’t quite work: depending on random timing issues, another set of
results might be inserted after the second time we steal the highlight.&lt;/p&gt;

&lt;p&gt;Another problem with relying on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTimeout&lt;/code&gt; is that rendering the results is slow,
so our delayed highlight stealing code can sometimes get stuck behind delayed result rendering code
in the timer queue–another nondeterministic race that adds up to
noticeable blue flickering, or the highlight again getting stolen back by the results list.&lt;/p&gt;

&lt;p&gt;There’s another way to schedule future code execution in JavaScript: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requestAnimationFrame&lt;/code&gt;.
Where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTimeout(fn, n)&lt;/code&gt; asks the browser to call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fn&lt;/code&gt; &lt;strong&gt;at least&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;
milliseconds in the future, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requestAnimationFrame(fn)&lt;/code&gt; asks the browser to call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fn&lt;/code&gt;
&lt;strong&gt;on the very next frame&lt;/strong&gt;, just before it flushes the rendered page to the screen.
rAF allows the highlight stealing code to cut in line, undoing highlight changes
at the last possible instant.&lt;/p&gt;

&lt;p&gt;Using a single rAF wasn’t enough, for the same reasons that a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTimeout&lt;/code&gt;
wasn’t enough. However, chaining rAF calls allows multiple successive frames to be
altered, and this is just aggressive enough to work fairly well.&lt;/p&gt;

&lt;p&gt;The working highlight stealing code basically does this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// In response to each observed mutation event,
// steal the highlight on the current and the next two frames.
function onMutation() {
  stealHighlight();
  requestAnimationFrame(() =&amp;gt; {
    stealHighlight();
    requestAnimationFrame(() =&amp;gt; {
      stealHighlight();
    });
  });
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s a bit of a weird hack, but it certainly works well enough for beta testing:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;360&quot; src=&quot;https://www.youtube.com/embed/_LfBQSIBsRY&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;If you look carefully at the video, there’s some blue flicker that appears when I hit the space bar.
I think this is because the existing code trims the whitespace,
detects that the trimmed query hasn’t changed, and immediately re-renders,
while the prototype code isn’t quite that smart yet. The few milliseconds’ delay translates
into the highlighted top row getting rendered before the recommendation, and just
for a moment, that blue flicker is visible.&lt;/p&gt;

&lt;h4 id=&quot;links&quot;&gt;Links&lt;/h4&gt;

&lt;p&gt;The working highlight management code is &lt;a href=&quot;https://github.com/mozilla/universal-search/blob/master/lib/ui/highlight-manager.js&quot;&gt;here&lt;/a&gt;, if you’d like to read it.
It’s fairly complex: highlight management requires adjusting the
highlight in response to key or mouse events. That said, it’s heavily
commented, and might be interesting reading.&lt;/p&gt;

&lt;p&gt;If you’d like to learn more about this experiment, its &lt;a href=&quot;https://wiki.mozilla.org/Test_Pilot/Universal_Search&quot;&gt;wiki page&lt;/a&gt;
is a good place to start: you’ll find links to the github repos, UX artifacts, some producty discussion,
and contact info for the team, if you’d like to get involved.&lt;/p&gt;

&lt;p&gt;If you’re interested in the new Test Pilot, I’d suggest checking out &lt;a href=&quot;https://wiki.mozilla.org/Test_Pilot&quot;&gt;the wiki&lt;/a&gt;,
or Wil’s &lt;a href=&quot;http://micropipes.com/blog//2016/01/27/meet-the-new-test-pilot/&quot;&gt;blog post&lt;/a&gt; about it.&lt;/p&gt;

&lt;h4 id=&quot;comments&quot;&gt;Comments?&lt;/h4&gt;

&lt;p&gt;If you have questions or have spotted a typo, feel free to email or tweet at me.&lt;/p&gt;

&lt;p&gt;If you’d like to offer longer comments or a response, I’d like to encourage you to post your own response
on your own website, and share the link with me over email or twitter.&lt;/p&gt;
</description>
        <pubDate>Thu, 31 Mar 2016 23:42:55 +0000</pubDate>
        <link>https://6a68.net/2016/highlight-stealing-hack/</link>
        <guid isPermaLink="true">https://6a68.net/2016/highlight-stealing-hack/</guid>
        
        
        <category>mozilla</category>
        
        <category>front-end-programming</category>
        
        <category>hacks</category>
        
      </item>
    
  </channel>
</rss>
