
<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://jcbhmr.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://jcbhmr.com/" rel="alternate" type="text/html" /><updated>2026-04-07T19:48:20+00:00</updated><id>https://jcbhmr.com/feed.xml</id><title type="html">Jacob Hummer</title><subtitle>A far too meticulous web developer 💻</subtitle><author><name>Jacob Hummer</name><email>jcbhmr@outlook.com</email></author><entry><title type="html">‘“one” | “two” | string’ autocomplete TypeScript trick</title><link href="https://jcbhmr.com/2026/04/07/any-string-autocomplete-ts/" rel="alternate" type="text/html" title="‘“one” | “two” | string’ autocomplete TypeScript trick" /><published>2026-04-07T00:00:00+00:00</published><updated>2026-04-07T00:00:00+00:00</updated><id>https://jcbhmr.com/2026/04/07/any-string-autocomplete-ts</id><content type="html" xml:base="https://jcbhmr.com/2026/04/07/any-string-autocomplete-ts/"><![CDATA[<p>Have you ever wanted to suggest some strings but still allow any string? Like <code>&quot;GET&quot; | &quot;POST&quot; | string</code>? But then it just <em>doesn't work</em> like you want it to?</p>
<div><a href="https://www.typescriptlang.org/play/?&q=191#code/PTAEDkHsBcFNQBaQO6gOQCIDiBRAKhqAD6gYAKA8gMoHGgDO0ATgJYB2A5mqB7NPaCawAJgFcAxiNDRIoAFajGpRq06F67SaBbQ0A6AlgAoEKABGTSAENhsJdACeAB3iQAZtMPa2cJvVji0CyQbAD8oHgIVroCsAAeLoFSZrBRAG7BokwAdEZGji6gABJ4eGQAsnxIwqAAvKS4tCTk1E0MzOwcJmCgoAB6od29wyOjYyN9EQgsAvRIogA2NSnKHWp5bqJsgcFsoMKQJWUAFAC2VZDCAFzFpRUXwgCUN2mQLDUA3kYj4iH0kAtYNkFpAOGcHo9vsNTONegMob0YbDhpNIjMGPMluZ4Bhjk4rEwrOdfI9QMTqjcVJ0MLkAL55A5HMjHDAYSFIuGgMhCegCADCeAASgAZADUVDIAEE+ThELAhNJZMwHKArGwarxoKrRDJfqcnIC4NlQABNSCiDHmrGa0BsGDTTjZIA">[TypeScript playground link]</a></div>
<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Note how '"GET" | "POST" | string' gets reduced to just "string" since it's the</span>
<span class="c1">// broadest type of the intersection? That's expected behaviour.</span>

<span class="kd">type</span> <span class="nx">HTTPMethod</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">GET</span><span class="dl">"</span> <span class="o">|</span> <span class="dl">"</span><span class="s2">POST</span><span class="dl">"</span> <span class="o">|</span> <span class="kr">string</span>
<span class="c1">//   ^?</span>
<span class="c1">//                        ^ This should be "string"</span>

<span class="kd">function</span> <span class="nx">doHTTP</span><span class="p">(</span><span class="nx">method</span><span class="p">:</span> <span class="nx">HTTPMethod</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">method</span><span class="p">)</span>
    <span class="c1">//          ^?</span>
    <span class="c1">//             ^ This should be "(parameter) method: string".</span>
<span class="p">}</span>

<span class="nx">doHTTP</span><span class="p">(</span><span class="dl">""</span><span class="p">)</span>
<span class="c1">//     ^ Press CTRL+SPACE here to try and get autocomplete. You should get nothing.</span>
</code></pre></div></div>
<blockquote>
<p>From the compiler's point of view, this is just a very fancy way of writing <code>string</code>. By the time we're looking for suggestions at [HTTPMethod], all the literals are lost.</p>
</blockquote>
<p>— <a href="https://github.com/Microsoft/TypeScript/issues/29729">microsoft/TypeScript#29729</a></p>
<p>The trick is to fool the type checker into thinking that the <code>| string</code> part of the union type is magically (somehow?) different than the type of the literals -- that way it doesn't get reduced to just <code>type T = string</code>. The magic is <code>string &amp; {}</code>.</p>
<div><a href="https://www.typescriptlang.org/play/?&q=191#code/PTAEEkBdQdwewE4GsDOBCAUByBPADgKagASAKqQAoCyBkAFnACagC8oARAOICip7oAHw4UA8gGU+g0AAoUkBAEsAdgHNQAMlABvAL4BKDCFDGAegH5DYY9Zu271k6FJ0FKUCgYBXADbMARkQA5LLyymqaunpSXLz8QuyiEuyBWABmnkoAxpAKcEqgjHBklNIAtrQMjABcJOTUFUx6NQBucArMWhg2mXkocN4EAHTecCplDYwGNkb2phbTVrMOTi5uHnA+-kTs0ngAhgh75ZAECFHHlTXF9fRM7IMYOliF19Ls7AYzyxQIBChuAGFSAAlAAyAGoxBQAIIA7igOinIiQOCgeQ4UB7JTMFS0TGeFE9Up4AYnQagACaG3cXl8oFx0DkilUoG8ChOh286CwRkGfL8BNAOGpmSxmK5qIAVp45Gj8EQsRimWEhdSYFjIOTnK5QDrmns2YwHi86m8lHBIABaLGWuiQSB4S0XO56IA">[TypeScript playground link]</a></div>
<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// It works!</span>

<span class="kd">type</span> <span class="nx">HTTPMethod</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">GET</span><span class="dl">"</span> <span class="o">|</span> <span class="dl">"</span><span class="s2">POST</span><span class="dl">"</span> <span class="o">|</span> <span class="p">(</span><span class="kr">string</span> <span class="o">&amp;</span> <span class="p">{})</span>
<span class="c1">//   ^?</span>
<span class="c1">//                        ^ This should be '(string &amp; {}) | "GET" | "POST"'</span>

<span class="kd">function</span> <span class="nx">doHTTP</span><span class="p">(</span><span class="nx">method</span><span class="p">:</span> <span class="nx">HTTPMethod</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
   <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">method</span><span class="p">)</span>
   <span class="c1">//          ^?</span>
   <span class="c1">//             ^ This should be "(parameter) method: HTTPMethod".</span>
<span class="p">}</span>

<span class="nx">doHTTP</span><span class="p">(</span><span class="dl">""</span><span class="p">)</span>
<span class="c1">//     ^ Press CTRL+SPACE here to try and get autocomplete. You should get string literals!</span>

<span class="c1">// ...but you can also just type any string you want. This is valid.</span>
<span class="nx">doHTTP</span><span class="p">(</span><span class="dl">"</span><span class="s2">not-an-http-method</span><span class="dl">"</span><span class="p">)</span>
</code></pre></div></div>
<p>The <a href="https://www.npmjs.com/package/type-fest">type-fest</a> npm package has a type for this exact use-case: <a href="https://github.com/sindresorhus/type-fest/blob/main/source/literal-union.d.ts"><code>LiteralUnion</code></a>.</p>
<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="kd">type</span> <span class="p">{</span><span class="nx">LiteralUnion</span><span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">type-fest</span><span class="dl">'</span><span class="p">;</span>

<span class="c1">// Before</span>

<span class="kd">type</span> <span class="nx">Pet</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">dog</span><span class="dl">'</span> <span class="o">|</span> <span class="dl">'</span><span class="s1">cat</span><span class="dl">'</span> <span class="o">|</span> <span class="kr">string</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">petWithoutAutocomplete</span><span class="p">:</span> <span class="nx">Pet</span> <span class="o">=</span> <span class="dl">''</span><span class="p">;</span>
<span class="c1">// Start typing in your TypeScript-enabled IDE.</span>
<span class="c1">// You **will not** get auto-completion for `dog` and `cat` literals.</span>

<span class="c1">// After</span>

<span class="kd">type</span> <span class="nx">Pet2</span> <span class="o">=</span> <span class="nx">LiteralUnion</span><span class="o">&lt;</span><span class="dl">'</span><span class="s1">dog</span><span class="dl">'</span> <span class="o">|</span> <span class="dl">'</span><span class="s1">cat</span><span class="dl">'</span><span class="p">,</span> <span class="kr">string</span><span class="o">&gt;</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">petWithAutoComplete</span><span class="p">:</span> <span class="nx">Pet2</span> <span class="o">=</span> <span class="dl">''</span><span class="p">;</span>
<span class="c1">// You **will** get auto-completion for `dog` and `cat` literals.</span>
</code></pre></div></div>
<p>There was a TypeScript GitHub issue opened about having this <code>&quot;one&quot; | &quot;two&quot; | string</code> literal stuff work out of the box, but it didn't go anywhere. <a href="https://github.com/Microsoft/TypeScript/issues/29729">Microsoft/TypeScript#29729</a></p>]]></content><author><name>Jacob Hummer</name><email>jcbhmr@outlook.com</email></author><summary type="html"><![CDATA[Have you ever wanted to suggest some strings but still allow any string? Like &quot;GET&quot; | &quot;POST&quot; | string? But then it just doesn't work like you want it to?]]></summary></entry><entry><title type="html">Node.js platform/arch possible values</title><link href="https://jcbhmr.com/2025/12/19/node-platform-arch-values/" rel="alternate" type="text/html" title="Node.js platform/arch possible values" /><published>2025-12-19T00:00:00+00:00</published><updated>2025-12-19T00:00:00+00:00</updated><id>https://jcbhmr.com/2025/12/19/node-platform-arch-values</id><content type="html" xml:base="https://jcbhmr.com/2025/12/19/node-platform-arch-values/"><![CDATA[<p>The official Node.js docs (v25.2.1) say that <code>process.platform</code> can be <code>'aix' | 'darwin' | 'freebsd' | 'linux' | 'openbsd' | 'sunos' | 'win32'</code> and <code>process.arch</code> can be <code>'arm' | 'arm64' | 'ia32' | 'loong64' | 'mips' | 'mipsel' | 'ppc64' | 'riscv64' | 's390' | 's390x' | 'x64'</code>. That's not quite true. This is my chronicle as I explore where the values come from.</p>
<p><strong>TL;DR:</strong></p>
<ul>
<li><strong><code>node:process</code> <code>platform</code> &amp; <code>node:os</code> <code>platform()</code>:</strong> <code>&quot;netbsd&quot;</code>, <code>&quot;os390&quot;</code>, <code>&quot;win32&quot;</code>, <code>&quot;darwin&quot;</code>, <code>&quot;sunos&quot;</code>, <code>&quot;freebsd&quot;</code>, <code>&quot;openbsd&quot;</code>, <code>&quot;linux&quot;</code>, <code>&quot;android&quot;</code>, <code>&quot;aix&quot;</code>, <code>&quot;os400&quot;</code>, <code>&quot;ios&quot;</code>, <code>&quot;openharmony&quot;</code>, <code>&quot;emscripten&quot;</code>, <code>&quot;wasm&quot;</code>, <code>&quot;wasi&quot;</code>, <code>&quot;cloudabi&quot;</code></li>
<li><strong><code>node:process</code> <code>arch</code> &amp; <code>node:os</code> <code>arch()</code>:</strong> <code>&quot;s390x&quot;</code>, <code>&quot;arm64&quot;</code>, <code>&quot;arm&quot;</code>, <code>&quot;ia32&quot;</code>, <code>&quot;mipsel&quot;</code>, <code>&quot;mips&quot;</code>, <code>&quot;mips64el&quot;</code>, <code>&quot;ppc64&quot;</code>, <code>&quot;x64&quot;</code>, <code>&quot;riscv64&quot;</code>, <code>&quot;riscv32&quot;</code>, <code>&quot;loong64&quot;</code></li>
<li><strong><code>node:os</code> <code>machine()</code>:</strong> <code>x86_64</code>, <code>ia64</code>, <code>i386</code>, <code>i486</code>, <code>i586</code>, <code>i686</code>, <code>mips</code>, <code>alpha</code>, <code>powerpc</code>, <code>sh</code>, <code>arm</code>, <code>unknown</code> on Windows; <code>ppc64</code> or <em>any <code>uname -m</code> value</em> on Unix.</li>
</ul>
<h2 id="codenodeprocesscode-codeplatformcode-amp-codenodeoscode-codeplatformcode"><code>node:process</code> <code>platform</code> &amp; <code>node:os</code> <code>platform()</code></h2>
<p>The Node.js process object is defined across some C++ files as a global object. The <code>node:process</code> module just reexports it with all the appropriate named properties. This means there's nothing to see in <code>lib/process.js</code></p>
<div><a href="https://github.com/nodejs/node/blob/05f8772096f974190b11eabce0ea657bc5c8c1b1/lib/process.js"><code>lib/process.js</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">'</span><span class="s1">use strict</span><span class="dl">'</span><span class="p">;</span>

<span class="c1">// Re-export process as a built-in module</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="nx">process</span><span class="p">;</span>
</code></pre></div></div>
<p>Instead, we have to jump to the <code>src/node_*.cc</code> files to see anything that defines <code>process.*</code> properties &amp; methods. Don't worry about where and how this v8 <code>process</code> object gets set as a global variable; that's not important right now.</p>
<div><a href="https://github.com/nodejs/node/blob/05f8772096f974190b11eabce0ea657bc5c8c1b1/src/node_process_object.cc#L132"><code>src/node_process_object.cc</code></a></div>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// process.platform</span>
<span class="n">READONLY_STRING_PROPERTY</span><span class="p">(</span><span class="n">process</span><span class="p">,</span> <span class="s">"platform"</span><span class="p">,</span> <span class="n">per_process</span><span class="o">::</span><span class="n">metadata</span><span class="p">.</span><span class="n">platform</span><span class="p">);</span>
</code></pre></div></div>
<p>What's this <code>per_process::metadata</code> struct? Where is it defined? It must be some kind of singleton/constant since it's being used to access <code>.platform</code> as a property. Sure enough, it is!</p>
<div><a href="https://github.com/nodejs/node/blob/05f8772096f974190b11eabce0ea657bc5c8c1b1/src/node_metadata.h#L152"><code>src/node_metadata.h</code></a></div>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Per-process global</span>
<span class="k">namespace</span> <span class="n">per_process</span> <span class="p">{</span>
<span class="k">extern</span> <span class="n">Metadata</span> <span class="n">metadata</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<div><a href="https://github.com/nodejs/node/blob/05f8772096f974190b11eabce0ea657bc5c8c1b1/src/node_metadata.cc#L54"><code>src/node_metadata.cc</code></a></div>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">namespace</span> <span class="n">per_process</span> <span class="p">{</span>
<span class="n">Metadata</span> <span class="n">metadata</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p><code>node::Metadata</code> is a class that has a single constructor that sets <code>.arch</code> and <code>.platform</code> (<code>std::string</code>-s) to some <code>#define</code>-ed macro string literals.</p>
<div><a href="https://github.com/nodejs/node/blob/05f8772096f974190b11eabce0ea657bc5c8c1b1/src/node_metadata.h#L147"><code>src/node_metadata.h</code></a></div>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Metadata</span> <span class="p">{</span>
 <span class="nl">public:</span>
  <span class="n">Metadata</span><span class="p">();</span>
  <span class="n">Metadata</span><span class="p">(</span><span class="n">Metadata</span><span class="o">&amp;</span><span class="p">)</span> <span class="o">=</span> <span class="k">delete</span><span class="p">;</span>
  <span class="n">Metadata</span><span class="p">(</span><span class="n">Metadata</span><span class="o">&amp;&amp;</span><span class="p">)</span> <span class="o">=</span> <span class="k">delete</span><span class="p">;</span>
  <span class="n">Metadata</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="n">Metadata</span><span class="o">&amp;</span><span class="p">)</span> <span class="o">=</span> <span class="k">delete</span><span class="p">;</span>
  <span class="n">Metadata</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="n">Metadata</span><span class="o">&amp;&amp;</span><span class="p">)</span> <span class="o">=</span> <span class="k">delete</span><span class="p">;</span>

  <span class="k">struct</span> <span class="nc">Versions</span> <span class="p">{</span>
    <span class="c1">// -- ✂️ SNIP --</span>
  <span class="p">}</span>

  <span class="n">Versions</span> <span class="n">versions</span><span class="p">;</span>
  <span class="k">const</span> <span class="n">Release</span> <span class="n">release</span><span class="p">;</span>
  <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">arch</span><span class="p">;</span>
  <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">platform</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>
<div><a href="https://github.com/nodejs/node/blob/05f8772096f974190b11eabce0ea657bc5c8c1b1/src/node_metadata.cc#L205"><code>src/node_metadata.cc</code></a></div>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Metadata</span><span class="o">::</span><span class="n">Metadata</span><span class="p">()</span> <span class="o">:</span> <span class="n">arch</span><span class="p">(</span><span class="n">NODE_ARCH</span><span class="p">),</span> <span class="n">platform</span><span class="p">(</span><span class="n">NODE_PLATFORM</span><span class="p">)</span> <span class="p">{}</span>
</code></pre></div></div>
<p>So far we know that <code>node.platform</code> is set to whatever value <code>NODE_PLATFORM</code> is set to. Where is that set? It's set by the <a href="https://gyp.gsrc.io/">GYP build system</a> configuration.</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
  <span class="s">'target_name'</span><span class="p">:</span> <span class="s">'&lt;(node_core_target_name)'</span><span class="p">,</span>
  <span class="s">'type'</span><span class="p">:</span> <span class="s">'executable'</span><span class="p">,</span>

  <span class="s">'defines'</span><span class="p">:</span> <span class="p">[</span>
    <span class="s">'NODE_ARCH="&lt;(target_arch)"'</span><span class="p">,</span>
    <span class="s">'NODE_PLATFORM="&lt;(OS)"'</span><span class="p">,</span> <span class="c1"># 👈
</span>    <span class="s">'NODE_WANT_INTERNALS=1'</span><span class="p">,</span>
  <span class="p">],</span>

  <span class="c1"># -- ✂️ SNIP --
</span><span class="p">}</span>
</code></pre></div></div>
<p>What's this <code>OS</code> variable? Where does it come from? It is a <a href="https://gyp.gsrc.io/docs/InputFormatReference.md#predefined-variables">GYP predefined variable</a>. I don't really know if you're supposed to manually set it or if it's inferred from your host platform.</p>
<blockquote>
<ul>
<li>
<p><code>OS</code>: The name of the operating system that the generator produces output for. Common values for values for <code>OS</code> are:</p>
<ul>
<li><code>'linux'</code></li>
<li><code>'mac'</code></li>
<li><code>'win'</code></li>
</ul>
<p>But other values may be encountered and this list should not be considered exhaustive.</p>
</li>
</ul>
</blockquote>
<p>— <a href="https://gyp.gsrc.io/docs/InputFormatReference.md#predefined-variables">GYP input format reference docs</a></p>
<p>There are other files that appear to overwrite the value of <code>NODE_PLATFORM</code> to other values that are more specialized than just <code>&lt;(OS)</code>.</p>
<div><a href="https://github.com/nodejs/node/blob/05f8772096f974190b11eabce0ea657bc5c8c1b1/node.gypi#L69"><code>node.gypi</code></a></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span> <span class="s">'OS=="win"'</span><span class="p">,</span> <span class="p">{</span>
  <span class="s">'defines!'</span><span class="p">:</span> <span class="p">[</span>
    <span class="s">'NODE_PLATFORM="win"'</span><span class="p">,</span>
  <span class="p">],</span>
  <span class="s">'defines'</span><span class="p">:</span> <span class="p">[</span>
    <span class="s">'FD_SETSIZE=1024'</span><span class="p">,</span>
    <span class="c1"># we need to use node's preferred "win32" rather than gyp's preferred "win"
</span>    <span class="s">'NODE_PLATFORM="win32"'</span><span class="p">,</span> <span class="c1"># 👈
</span>    <span class="s">'_UNICODE=1'</span><span class="p">,</span>
  <span class="p">],</span>
  <span class="c1"># -- ✂️ SNIP --
</span><span class="p">]</span>
</code></pre></div></div>
<div><a href="https://github.com/nodejs/node/blob/05f8772096f974190b11eabce0ea657bc5c8c1b1/node.gypi#L257"><code>node.gypi</code></a></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span> <span class="s">'OS=="mac"'</span><span class="p">,</span> <span class="p">{</span>
  <span class="c1"># linking Corefoundation is needed since certain macOS debugging tools
</span>  <span class="c1"># like Instruments require it for some features. Security is needed for
</span>  <span class="c1"># --use-system-ca.
</span>  <span class="s">'libraries'</span><span class="p">:</span> <span class="p">[</span> <span class="s">'-framework CoreFoundation -framework Security'</span> <span class="p">],</span>
  <span class="s">'defines!'</span><span class="p">:</span> <span class="p">[</span>
    <span class="s">'NODE_PLATFORM="mac"'</span><span class="p">,</span>
  <span class="p">],</span>
  <span class="s">'defines'</span><span class="p">:</span> <span class="p">[</span>
    <span class="c1"># we need to use node's preferred "darwin" rather than gyp's preferred "mac"
</span>    <span class="s">'NODE_PLATFORM="darwin"'</span><span class="p">,</span> <span class="c1"># 👈
</span>  <span class="p">],</span>
<span class="p">}],</span>
</code></pre></div></div>
<div><a href="https://github.com/nodejs/node/blob/05f8772096f974190b11eabce0ea657bc5c8c1b1/node.gypi#L310"><code>node.gypi</code></a></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span> <span class="s">'OS=="solaris"'</span><span class="p">,</span> <span class="p">{</span>
  <span class="s">'libraries'</span><span class="p">:</span> <span class="p">[</span>
    <span class="s">'-lkstat'</span><span class="p">,</span>
    <span class="s">'-lumem'</span><span class="p">,</span>
  <span class="p">],</span>
  <span class="s">'defines!'</span><span class="p">:</span> <span class="p">[</span>
    <span class="s">'NODE_PLATFORM="solaris"'</span><span class="p">,</span>
  <span class="p">],</span>
  <span class="s">'defines'</span><span class="p">:</span> <span class="p">[</span>
    <span class="c1"># we need to use node's preferred "sunos"
</span>    <span class="c1"># rather than gyp's preferred "solaris"
</span>    <span class="s">'NODE_PLATFORM="sunos"'</span><span class="p">,</span> <span class="c1"># 👈
</span>  <span class="p">],</span>
<span class="p">}],</span>
</code></pre></div></div>
<div><a href="https://github.com/nodejs/node/blob/05f8772096f974190b11eabce0ea657bc5c8c1b1/common.gypi#L730"><code>common.gypi</code></a></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="s">'OS == "zos"'</span><span class="p">,</span> <span class="p">{</span>
  <span class="s">'defines'</span><span class="p">:</span> <span class="p">[</span>
    <span class="s">'_XOPEN_SOURCE_EXTENDED'</span><span class="p">,</span>
    <span class="s">'_XOPEN_SOURCE=600'</span><span class="p">,</span>
    <span class="s">'_UNIX03_THREADS'</span><span class="p">,</span>
    <span class="s">'_UNIX03_WITHDRAWN'</span><span class="p">,</span>
    <span class="s">'_UNIX03_SOURCE'</span><span class="p">,</span>
    <span class="s">'_OPEN_SYS_SOCK_IPV6'</span><span class="p">,</span>
    <span class="s">'_OPEN_SYS_FILE_EXT=1'</span><span class="p">,</span>
    <span class="s">'_POSIX_SOURCE'</span><span class="p">,</span>
    <span class="s">'_OPEN_SYS'</span><span class="p">,</span>
    <span class="s">'_OPEN_SYS_IF_EXT'</span><span class="p">,</span>
    <span class="s">'_OPEN_SYS_SOCK_IPV6'</span><span class="p">,</span>
    <span class="s">'_OPEN_MSGQ_EXT'</span><span class="p">,</span>
    <span class="s">'_LARGE_TIME_API'</span><span class="p">,</span>
    <span class="s">'_ALL_SOURCE'</span><span class="p">,</span>
    <span class="s">'_AE_BIMODAL=1'</span><span class="p">,</span>
    <span class="s">'__IBMCPP_TR1__'</span><span class="p">,</span>
    <span class="s">'NODE_PLATFORM="os390"'</span><span class="p">,</span> <span class="c1"># 👈
</span>    <span class="s">'PATH_MAX=1024'</span><span class="p">,</span>
    <span class="s">'_ENHANCED_ASCII_EXT=0xFFFFFFFF'</span><span class="p">,</span>
    <span class="s">'_Export=extern'</span><span class="p">,</span>
    <span class="s">'__static_assert=static_assert'</span><span class="p">,</span>
  <span class="p">],</span>
  <span class="c1"># -- ✂️ SNIP --
</span><span class="p">]</span>
</code></pre></div></div>
<p>But what are the other possible values for this <code>OS</code> variable? We have to take a look at how GYP initializes that variable with a default value. It seems like all code paths call <code>gyp.common.GetFlavor(params)</code> somehow to get an initial OS name and then sometimes do custom configuration and initialization based on the return value (if win, if linux, if mac, etc.).</p>
<div><a href="https://github.com/nodejs/gyp-next/blob/732b09edc711ce3bad2df6db02ba8d5f315ca375/pylib/gyp/generator/compile_commands_json.py#L42">nodejs/gyp-next: <code>pylib/gyp/generator/compile_commands_json.py</code></a></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">default_variables</span><span class="p">.</span><span class="n">setdefault</span><span class="p">(</span><span class="s">"OS"</span><span class="p">,</span> <span class="n">gyp</span><span class="p">.</span><span class="n">common</span><span class="p">.</span><span class="n">GetFlavor</span><span class="p">(</span><span class="n">params</span><span class="p">))</span>
</code></pre></div></div>
<p>The <code>GetFlavor()</code> function delegates to <code>GetFlavorByPlatform()</code>...</p>
<div><a href="https://github.com/nodejs/gyp-next/blob/732b09edc711ce3bad2df6db02ba8d5f315ca375/pylib/gyp/common.py#L513">nodejs/gyp-next: <code>pylib/gyp/common.py</code></a></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">GetFlavor</span><span class="p">(</span><span class="n">params</span><span class="p">):</span>
    <span class="k">if</span> <span class="s">"flavor"</span> <span class="ow">in</span> <span class="n">params</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">params</span><span class="p">[</span><span class="s">"flavor"</span><span class="p">]</span>

    <span class="n">defines</span> <span class="o">=</span> <span class="n">GetCompilerPredefines</span><span class="p">()</span>
    <span class="k">if</span> <span class="s">"__EMSCRIPTEN__"</span> <span class="ow">in</span> <span class="n">defines</span><span class="p">:</span>
        <span class="k">return</span> <span class="s">"emscripten"</span>
    <span class="k">if</span> <span class="s">"__wasm__"</span> <span class="ow">in</span> <span class="n">defines</span><span class="p">:</span>
        <span class="k">return</span> <span class="s">"wasi"</span> <span class="k">if</span> <span class="s">"__wasi__"</span> <span class="ow">in</span> <span class="n">defines</span> <span class="k">else</span> <span class="s">"wasm"</span>

    <span class="k">return</span> <span class="n">GetFlavorByPlatform</span><span class="p">()</span>
</code></pre></div></div>
<p>...which is where the real <code>if sys.platform == &quot;...&quot;</code> magic happens.</p>
<div><a href="https://github.com/nodejs/gyp-next/blob/732b09edc711ce3bad2df6db02ba8d5f315ca375/pylib/gyp/common.py#L485">nodejs/gyp-next: <code>pylib/gyp/common.py</code></a></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">GetFlavorByPlatform</span><span class="p">():</span>
    <span class="s">"""Returns |params.flavor| if it's set, the system's default flavor else."""</span>
    <span class="n">flavors</span> <span class="o">=</span> <span class="p">{</span>
        <span class="s">"cygwin"</span><span class="p">:</span> <span class="s">"win"</span><span class="p">,</span>
        <span class="s">"win32"</span><span class="p">:</span> <span class="s">"win"</span><span class="p">,</span>
        <span class="s">"darwin"</span><span class="p">:</span> <span class="s">"mac"</span><span class="p">,</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="n">sys</span><span class="p">.</span><span class="n">platform</span> <span class="ow">in</span> <span class="n">flavors</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">flavors</span><span class="p">[</span><span class="n">sys</span><span class="p">.</span><span class="n">platform</span><span class="p">]</span>
    <span class="k">if</span> <span class="n">sys</span><span class="p">.</span><span class="n">platform</span><span class="p">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">"sunos"</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">"solaris"</span>
    <span class="k">if</span> <span class="n">sys</span><span class="p">.</span><span class="n">platform</span><span class="p">.</span><span class="n">startswith</span><span class="p">((</span><span class="s">"dragonfly"</span><span class="p">,</span> <span class="s">"freebsd"</span><span class="p">)):</span>
        <span class="k">return</span> <span class="s">"freebsd"</span>
    <span class="k">if</span> <span class="n">sys</span><span class="p">.</span><span class="n">platform</span><span class="p">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">"openbsd"</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">"openbsd"</span>
    <span class="k">if</span> <span class="n">sys</span><span class="p">.</span><span class="n">platform</span><span class="p">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">"netbsd"</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">"netbsd"</span>
    <span class="k">if</span> <span class="n">sys</span><span class="p">.</span><span class="n">platform</span><span class="p">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">"aix"</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">"aix"</span>
    <span class="k">if</span> <span class="n">sys</span><span class="p">.</span><span class="n">platform</span><span class="p">.</span><span class="n">startswith</span><span class="p">((</span><span class="s">"os390"</span><span class="p">,</span> <span class="s">"zos"</span><span class="p">)):</span>
        <span class="k">return</span> <span class="s">"zos"</span>
    <span class="k">if</span> <span class="n">sys</span><span class="p">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s">"os400"</span><span class="p">:</span>
        <span class="k">return</span> <span class="s">"os400"</span>

    <span class="k">return</span> <span class="s">"linux"</span>
</code></pre></div></div>
<p>All told, the returned flavor string can be <code>&quot;emscripten&quot;</code>, <code>&quot;wasi&quot;</code>, <code>&quot;wasm&quot;</code>, <code>&quot;win&quot;</code>, <code>&quot;mac&quot;</code>, <code>&quot;solaris&quot;</code>, <code>&quot;freebsd&quot;</code>, <code>&quot;openbsd&quot;</code>, <code>&quot;netbsd&quot;</code>, <code>&quot;aix&quot;</code>, <code>&quot;zos&quot;</code>, <code>&quot;os400&quot;</code>, <code>&quot;linux&quot;</code>, or any other custom name set by <code>params[&quot;flavor&quot;]</code>.</p>
<p>So where does the Node.js build system set <code>-DOS=&lt;something&gt;</code>? Node.js doesn't use GYP directly, instead the official build procedure is to run <code>./configure</code> and <code>make -j4</code> (on Unix &amp; macOS). The <code>./configure</code> script is a <code>/bin/sh</code> script that reexecutes itself as a Python script and then imports <code>./configure.py</code> if the Python version is satisfactory. That <code>configure.py</code> file is where the magic happens.</p>
<div><a href="https://github.com/nodejs/node/blob/dcb9573d0f90ee0d66001d26514bbdcfd8e0610e/configure.py#L47"><code>configure.py</code></a></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">valid_os</span> <span class="o">=</span> <span class="p">(</span><span class="s">'win'</span><span class="p">,</span> <span class="s">'mac'</span><span class="p">,</span> <span class="s">'solaris'</span><span class="p">,</span> <span class="s">'freebsd'</span><span class="p">,</span> <span class="s">'openbsd'</span><span class="p">,</span> <span class="s">'linux'</span><span class="p">,</span>
            <span class="s">'android'</span><span class="p">,</span> <span class="s">'aix'</span><span class="p">,</span> <span class="s">'cloudabi'</span><span class="p">,</span> <span class="s">'os400'</span><span class="p">,</span> <span class="s">'ios'</span><span class="p">,</span> <span class="s">'openharmony'</span><span class="p">)</span>
</code></pre></div></div>
<div><a href="https://github.com/nodejs/node/blob/dcb9573d0f90ee0d66001d26514bbdcfd8e0610e/configure.py#L139"><code>configure.py</code></a></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">parser</span><span class="p">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">'--dest-os'</span><span class="p">,</span>
    <span class="n">action</span><span class="o">=</span><span class="s">'store'</span><span class="p">,</span>
    <span class="n">dest</span><span class="o">=</span><span class="s">'dest_os'</span><span class="p">,</span>
    <span class="n">choices</span><span class="o">=</span><span class="n">valid_os</span><span class="p">,</span>
    <span class="n">help</span><span class="o">=</span><span class="sa">f</span><span class="s">"operating system to build for (</span><span class="si">{</span><span class="s">', '</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">valid_os</span><span class="p">)</span><span class="si">}</span><span class="s">)"</span><span class="p">)</span>
</code></pre></div></div>
<div><a href="https://github.com/nodejs/node/blob/dcb9573d0f90ee0d66001d26514bbdcfd8e0610e/configure.py#L2388"><code>configure.py</code></a></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># determine the "flavor" (operating system) we're building for,
# leveraging gyp's GetFlavor function
</span><span class="n">flavor_params</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">if</span> <span class="n">options</span><span class="p">.</span><span class="n">dest_os</span><span class="p">:</span>
  <span class="n">flavor_params</span><span class="p">[</span><span class="s">'flavor'</span><span class="p">]</span> <span class="o">=</span> <span class="n">options</span><span class="p">.</span><span class="n">dest_os</span>
<span class="n">flavor</span> <span class="o">=</span> <span class="n">GetFlavor</span><span class="p">(</span><span class="n">flavor_params</span><span class="p">)</span>
</code></pre></div></div>
<p><sup>Yes, it's the same <code>gyp.common.GetFlavor()</code> function</sup></p>
<p>This means that the OS <strong>when set manually</strong> (for cross compiling or whatever) must be one of <code>'win'</code>, <code>'mac'</code>, <code>'solaris'</code>, <code>'freebsd'</code>, <code>'openbsd'</code>, <code>'linux'</code>, <code>'android'</code>, <code>'aix'</code>, <code>'cloudabi'</code>, <code>'os400'</code>, <code>'ios'</code>, or <code>'openharmony'</code>. But if it's <strong>not set at all</strong> (if <code>options.dest_os</code> is falsey) then it can be any of the possible return values from <code>GetFlavor()</code> with the knowledge that <code>params[&quot;flavor&quot;]</code> is <strong>not set</strong>. <code>GetCompilerPredefines()</code> may still return <code>__EMSCRIPTEN__</code>, <code>__wasm__</code>, or <code>__wasi__</code> though so we can't rule those out as impossible values. That means the total combined list is:</p>
<ul>
<li><code>&quot;emscripten&quot;</code></li>
<li><code>&quot;wasi&quot;</code></li>
<li><code>&quot;wasm&quot;</code></li>
<li><code>&quot;netbsd&quot;</code></li>
<li><code>&quot;zos&quot;</code></li>
<li><code>&quot;win&quot;</code></li>
<li><code>&quot;mac&quot;</code></li>
<li><code>&quot;solaris&quot;</code></li>
<li><code>&quot;freebsd&quot;</code></li>
<li><code>&quot;openbsd&quot;</code></li>
<li><code>&quot;linux&quot;</code></li>
<li><code>&quot;android&quot;</code></li>
<li><code>&quot;aix&quot;</code></li>
<li><code>&quot;cloudabi&quot;</code></li>
<li><code>&quot;os400&quot;</code></li>
<li><code>&quot;ios&quot;</code></li>
<li><code>&quot;openharmony&quot;</code></li>
</ul>
<p>But some of these values, remember, have special mappings to Node.js <code>NODE_PLATFORM</code> values.</p>
<ul>
<li><code>zos</code> becomes <code>os390</code></li>
<li><code>solaris</code> becomes <code>sunos</code></li>
<li><code>mac</code> becomes <code>darwin</code></li>
<li><code>win</code> becomes <code>win32</code></li>
</ul>
<p>All together here's a list of <strong>all</strong> the possible Node.js <code>NODE_PLATFORM</code> (and by extension <code>process.platform</code> &amp; friends) values with some usage numbers from a quick GitHub search:</p>
<ul>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29emscripten%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">0 matches</a> <code>&quot;emscripten&quot;</code></li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29wasi%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">1 matches</a> <code>&quot;wasi&quot;</code></li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29wasm%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">0 matches</a> <code>&quot;wasm&quot;</code></li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29netbsd%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">114 matches</a> <code>&quot;netbsd&quot;</code></li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29os390%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">284 matches</a> <code>&quot;os390&quot;</code> (<code>&quot;zos&quot;</code> in GYP)</li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29win32%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">196 matches</a> <code>&quot;win32&quot;</code> (<code>&quot;win&quot;</code> in GYP)</li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29darwin%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">198 matches</a> <code>&quot;darwin&quot;</code> (<code>&quot;mac&quot;</code> in GYP)</li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29sunos%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">215 matches</a> <code>&quot;sunos&quot;</code> (<code>&quot;solaris&quot;</code> in GYP)</li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29freebsd%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">211 matches</a> <code>&quot;freebsd&quot;</code></li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29openbsd%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">223 matches</a> <code>&quot;openbsd&quot;</code></li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29linux%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">148 matches</a> <code>&quot;linux&quot;</code></li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29android%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">198 matches</a> <code>&quot;android&quot;</code></li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29aix%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">240 matches</a> <code>&quot;aix&quot;</code></li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29cloudabi%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">0 matches</a> <code>&quot;cloudabi&quot;</code> <sup><a href="https://github.com/search?q=%2F%28%3F-i%29%28%22%7C%27%29cloudabi%28%22%7C%27%29%2F+%28path%3A%2F%5C.%5Bcm%5D%3F%5Bjt%5Dsx%3F%24%2F+OR+path%3A%2F%28%5E%7C%5C%2F%29package%5C.json%24%2F%29&amp;type=code">Yes, really.</a></sup></li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29os400%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">1.1k matches</a> <code>&quot;os400&quot;</code></li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29ios%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">200 matches</a> <code>&quot;ios&quot;</code></li>
<li><a href="https://github.com/search?q=%2F%28process%5C.platform%7Cos%5C.platform%5C%28%5C%29%29%5Cs*%3D%3D%3D%3F%5Cs*%28%22%7C%27%29openharmony%28%22%7C%27%29%2F+%28language%3AJavaScript+OR+language%3ATypeScript%29&amp;type=code">229 matches</a> <code>&quot;openharmony&quot;</code></li>
</ul>
<p>Note that a few of these values are extremely rare, but they are sort of <em>possible</em> depending on how you interpret &quot;possible&quot; in this situation.</p>
<h2 id="codenodeprocesscode-codearchcode-amp-codenodeoscode-codearchcode"><code>node:process</code> <code>arch</code> &amp; <code>node:os</code> <code>arch()</code></h2>
<p>The first few layers of <code>platform.arch</code> are quite similar to <code>node.platform</code>; it's just sourced from a different macro <code>NODE_ARCH</code>, which is set in a different way.</p>
<div><a href="https://github.com/nodejs/node/blob/05f8772096f974190b11eabce0ea657bc5c8c1b1/src/node_process_object.cc#L129"><code>src/node_process_object.cc</code></a></div>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// process.arch</span>
<span class="n">READONLY_STRING_PROPERTY</span><span class="p">(</span><span class="n">process</span><span class="p">,</span> <span class="s">"arch"</span><span class="p">,</span> <span class="n">per_process</span><span class="o">::</span><span class="n">metadata</span><span class="p">.</span><span class="n">arch</span><span class="p">);</span>
</code></pre></div></div>
<p>And we know from the above <code>process.platform</code> investigation that <code>per_process::metadata.arch</code> is set to <code>NODE_ARCH</code>.</p>
<div><a href="https://github.com/nodejs/node/blob/05f8772096f974190b11eabce0ea657bc5c8c1b1/src/node_metadata.cc#L205"><code>src/node_metadata.cc</code></a></div>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Metadata</span><span class="o">::</span><span class="n">Metadata</span><span class="p">()</span> <span class="o">:</span> <span class="n">arch</span><span class="p">(</span><span class="n">NODE_ARCH</span><span class="p">),</span> <span class="n">platform</span><span class="p">(</span><span class="n">NODE_PLATFORM</span><span class="p">)</span> <span class="p">{}</span>
</code></pre></div></div>
<p>So where is this <code>NODE_ARCH</code> macro defined?</p>
<div><a href="https://github.com/nodejs/node/blob/4e1f39b678b37017ac9baa0971e3aeecd3b67b51/node.gyp#L555"><code>node.gyp</code></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
 <span class="s">'target_name'</span><span class="p">:</span> <span class="s">'&lt;(node_core_target_name)'</span><span class="p">,</span>
 <span class="s">'type'</span><span class="p">:</span> <span class="s">'executable'</span><span class="p">,</span>

 <span class="s">'defines'</span><span class="p">:</span> <span class="p">[</span>
   <span class="s">'NODE_ARCH="&lt;(target_arch)"'</span><span class="p">,</span> <span class="c1"># 👈
</span>   <span class="s">'NODE_PLATFORM="&lt;(OS)"'</span><span class="p">,</span>
   <span class="s">'NODE_WANT_INTERNALS=1'</span><span class="p">,</span>
 <span class="p">],</span>
 <span class="c1"># -- ✂️ SNIP --
</span><span class="p">}</span>
</code></pre></div></div>
<p>There's a <code>target_arch</code> variable defined somewhere. There's no monkey business with custom GYP-to-Node.js arch name conversions like there was with <code>NODE_PLATFORM</code>.</p>
<div><a href="https://github.com/nodejs/node/blob/4e1f39b678b37017ac9baa0971e3aeecd3b67b51/configure.py#L1581"><code>configure.py</code></a></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">host_arch</span> <span class="o">=</span> <span class="n">host_arch_win</span><span class="p">()</span> <span class="k">if</span> <span class="n">os</span><span class="p">.</span><span class="n">name</span> <span class="o">==</span> <span class="s">'nt'</span> <span class="k">else</span> <span class="n">host_arch_cc</span><span class="p">()</span>
<span class="n">target_arch</span> <span class="o">=</span> <span class="n">options</span><span class="p">.</span><span class="n">dest_cpu</span> <span class="ow">or</span> <span class="n">host_arch</span>
<span class="c1"># ia32 is preferred by the build tools (GYP) over x86 even if we prefer the latter
# the Makefile resets this to x86 afterward
</span><span class="k">if</span> <span class="n">target_arch</span> <span class="o">==</span> <span class="s">'x86'</span><span class="p">:</span>
  <span class="n">target_arch</span> <span class="o">=</span> <span class="s">'ia32'</span>
<span class="c1"># x86_64 is common across linuxes, allow it as an alias for x64
</span><span class="k">if</span> <span class="n">target_arch</span> <span class="o">==</span> <span class="s">'x86_64'</span><span class="p">:</span>
  <span class="n">target_arch</span> <span class="o">=</span> <span class="s">'x64'</span>
<span class="n">o</span><span class="p">[</span><span class="s">'variables'</span><span class="p">][</span><span class="s">'host_arch'</span><span class="p">]</span> <span class="o">=</span> <span class="n">host_arch</span>
<span class="n">o</span><span class="p">[</span><span class="s">'variables'</span><span class="p">][</span><span class="s">'target_arch'</span><span class="p">]</span> <span class="o">=</span> <span class="n">target_arch</span> <span class="c1"># 👈
</span></code></pre></div></div>
<p>First, let's look at <code>host_arch</code> to see what possible values it could be.</p>
<div><a href="https://github.com/nodejs/node/blob/4e1f39b678b37017ac9baa0971e3aeecd3b67b51/configure.py#L1465"><code>configure.py</code></a></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">host_arch_win</span><span class="p">():</span>
  <span class="s">"""Host architecture check using environ vars (better way to do this?)"""</span>

  <span class="n">observed_arch</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'PROCESSOR_ARCHITECTURE'</span><span class="p">,</span> <span class="s">'AMD64'</span><span class="p">)</span>
  <span class="n">arch</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'PROCESSOR_ARCHITEW6432'</span><span class="p">,</span> <span class="n">observed_arch</span><span class="p">)</span>

  <span class="n">matchup</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s">'AMD64'</span>  <span class="p">:</span> <span class="s">'x64'</span><span class="p">,</span>
    <span class="s">'arm'</span>    <span class="p">:</span> <span class="s">'arm'</span><span class="p">,</span>
    <span class="s">'mips'</span>   <span class="p">:</span> <span class="s">'mips'</span><span class="p">,</span>
    <span class="s">'ARM64'</span>  <span class="p">:</span> <span class="s">'arm64'</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="n">matchup</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">arch</span><span class="p">,</span> <span class="s">'x64'</span><span class="p">)</span>
</code></pre></div></div>
<div><a href="https://github.com/nodejs/node/blob/4e1f39b678b37017ac9baa0971e3aeecd3b67b51/configure.py#L1425"><code>configure.py</code></a></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">host_arch_cc</span><span class="p">():</span>
  <span class="s">"""Host architecture check using the CC command."""</span>

  <span class="k">if</span> <span class="n">sys</span><span class="p">.</span><span class="n">platform</span><span class="p">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">'zos'</span><span class="p">):</span>
    <span class="k">return</span> <span class="s">'s390x'</span>
  <span class="n">k</span> <span class="o">=</span> <span class="n">cc_macros</span><span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'CC_host'</span><span class="p">))</span>

  <span class="n">matchup</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s">'__aarch64__'</span> <span class="p">:</span> <span class="s">'arm64'</span><span class="p">,</span>
    <span class="s">'__arm__'</span>     <span class="p">:</span> <span class="s">'arm'</span><span class="p">,</span>
    <span class="s">'__i386__'</span>    <span class="p">:</span> <span class="s">'ia32'</span><span class="p">,</span>
    <span class="s">'__MIPSEL__'</span>  <span class="p">:</span> <span class="s">'mipsel'</span><span class="p">,</span>
    <span class="s">'__mips__'</span>    <span class="p">:</span> <span class="s">'mips'</span><span class="p">,</span>
    <span class="s">'__PPC64__'</span>   <span class="p">:</span> <span class="s">'ppc64'</span><span class="p">,</span>
    <span class="s">'__PPC__'</span>     <span class="p">:</span> <span class="s">'ppc64'</span><span class="p">,</span>
    <span class="s">'__x86_64__'</span>  <span class="p">:</span> <span class="s">'x64'</span><span class="p">,</span>
    <span class="s">'__s390x__'</span>   <span class="p">:</span> <span class="s">'s390x'</span><span class="p">,</span>
    <span class="s">'__riscv'</span>     <span class="p">:</span> <span class="s">'riscv'</span><span class="p">,</span>
    <span class="s">'__loongarch64'</span><span class="p">:</span> <span class="s">'loong64'</span><span class="p">,</span>
  <span class="p">}</span>

  <span class="n">rtn</span> <span class="o">=</span> <span class="s">'ia32'</span> <span class="c1"># default
</span>
  <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">matchup</span><span class="p">.</span><span class="n">items</span><span class="p">():</span>
    <span class="k">if</span> <span class="n">k</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="ow">and</span> <span class="n">k</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">!=</span> <span class="s">'0'</span><span class="p">:</span>
      <span class="n">rtn</span> <span class="o">=</span> <span class="n">value</span>
      <span class="k">break</span>

  <span class="k">if</span> <span class="n">rtn</span> <span class="o">==</span> <span class="s">'mipsel'</span> <span class="ow">and</span> <span class="s">'_LP64'</span> <span class="ow">in</span> <span class="n">k</span><span class="p">:</span>
    <span class="n">rtn</span> <span class="o">=</span> <span class="s">'mips64el'</span>

  <span class="k">if</span> <span class="n">rtn</span> <span class="o">==</span> <span class="s">'riscv'</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">k</span><span class="p">[</span><span class="s">'__riscv_xlen'</span><span class="p">]</span> <span class="o">==</span> <span class="s">'64'</span><span class="p">:</span>
      <span class="n">rtn</span> <span class="o">=</span> <span class="s">'riscv64'</span>
    <span class="k">else</span><span class="p">:</span>
      <span class="n">rtn</span> <span class="o">=</span> <span class="s">'riscv32'</span>

  <span class="k">return</span> <span class="n">rtn</span>
</code></pre></div></div>
<p><sup><code>cc_macros()</code> returns all predefined C compiler macros as a <code>dict</code></sup></p>
<p><code>host_arch_win()</code> possible values: <code>x64</code>, <code>arm</code>, <code>mips</code>, <code>arm64</code> <br />
<code>host_arch_cc()</code> possible values: <code>s390x</code>, <code>arm64</code>, <code>arm</code>, <code>ia32</code>, <code>mipsel</code>, <code>mips</code>, <code>mips64el</code>, <code>ppc64</code>, <code>x64</code>, <code>riscv64</code>, <code>riscv32</code>, <code>loong64</code></p>
<p>Now let's look at what options are valid <code>options.dest_cpu</code> <code>--dest-cpu</code> values.</p>
<div><a href="https://github.com/nodejs/node/blob/4e1f39b678b37017ac9baa0971e3aeecd3b67b51/configure.py#L49"><code>configure.py</code></a></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">valid_arch</span> <span class="o">=</span> <span class="p">(</span><span class="s">'arm'</span><span class="p">,</span> <span class="s">'arm64'</span><span class="p">,</span> <span class="s">'ia32'</span><span class="p">,</span> <span class="s">'mips'</span><span class="p">,</span> <span class="s">'mipsel'</span><span class="p">,</span> <span class="s">'mips64el'</span><span class="p">,</span>
              <span class="s">'ppc64'</span><span class="p">,</span> <span class="s">'x64'</span><span class="p">,</span> <span class="s">'x86'</span><span class="p">,</span> <span class="s">'x86_64'</span><span class="p">,</span> <span class="s">'s390x'</span><span class="p">,</span> <span class="s">'riscv64'</span><span class="p">,</span> <span class="s">'loong64'</span><span class="p">)</span>
</code></pre></div></div>
<div><a href="https://github.com/nodejs/node/blob/4e1f39b678b37017ac9baa0971e3aeecd3b67b51/configure.py#L110"><code>configure.py</code></a></div>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">parser</span><span class="p">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">'--dest-cpu'</span><span class="p">,</span>
    <span class="n">action</span><span class="o">=</span><span class="s">'store'</span><span class="p">,</span>
    <span class="n">dest</span><span class="o">=</span><span class="s">'dest_cpu'</span><span class="p">,</span>
    <span class="n">choices</span><span class="o">=</span><span class="n">valid_arch</span><span class="p">,</span>
    <span class="n">help</span><span class="o">=</span><span class="sa">f</span><span class="s">"CPU architecture to build for (</span><span class="si">{</span><span class="s">', '</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">valid_arch</span><span class="p">)</span><span class="si">}</span><span class="s">)"</span><span class="p">)</span>
</code></pre></div></div>
<p><strong>But</strong> <code>x86</code> gets mapped to <code>ia32</code> and <code>x86_64</code> gets mapped to <code>x64</code>. Here's the logic flow. Note that some values that aren't allowed in <code>--dest-cpu</code> can sneak in if <code>--dest-cpu</code> isn't set and the arch is inferred from the environment.</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">host_arch</span> <span class="o">=</span> <span class="n">host_arch_win</span><span class="p">()</span> <span class="k">if</span> <span class="n">os</span><span class="p">.</span><span class="n">name</span> <span class="o">==</span> <span class="s">'nt'</span> <span class="k">else</span> <span class="n">host_arch_cc</span><span class="p">()</span>
<span class="c1"># TYPE: "s390x" | "arm64" | "arm" | "ia32" | "mipsel" | "mips" | "mips64el" | "ppc64" | "x64" | "riscv64" | "riscv32" | "loong64"
</span>
<span class="n">target_arch</span> <span class="o">=</span> <span class="n">options</span><span class="p">.</span><span class="n">dest_cpu</span> <span class="ow">or</span> <span class="n">host_arch</span>
<span class="c1"># TYPE: "x86" | "x86_64" | "s390x" | "arm64" | "arm" | "ia32" | "mipsel" | "mips" | "mips64el" | "ppc64" | "x64" | "riscv64" | "riscv32" | "loong64"
</span>
<span class="c1"># ia32 is preferred by the build tools (GYP) over x86 even if we prefer the latter
# the Makefile resets this to x86 afterward
</span><span class="k">if</span> <span class="n">target_arch</span> <span class="o">==</span> <span class="s">'x86'</span><span class="p">:</span>
  <span class="n">target_arch</span> <span class="o">=</span> <span class="s">'ia32'</span>
<span class="c1"># target_arch TYPE: "x86_64" | "s390x" | "arm64" | "arm" | "ia32" | "mipsel" | "mips" | "mips64el" | "ppc64" | "x64" | "riscv64" | "riscv32" | "loong64"
</span>
<span class="c1"># x86_64 is common across linuxes, allow it as an alias for x64
</span><span class="k">if</span> <span class="n">target_arch</span> <span class="o">==</span> <span class="s">'x86_64'</span><span class="p">:</span>
  <span class="n">target_arch</span> <span class="o">=</span> <span class="s">'x64'</span>
<span class="c1"># target_arch TYPE: "s390x" | "arm64" | "arm" | "ia32" | "mipsel" | "mips" | "mips64el" | "ppc64" | "x64" | "riscv64" | "riscv32" | "loong64"
</span>
<span class="n">o</span><span class="p">[</span><span class="s">'variables'</span><span class="p">][</span><span class="s">'host_arch'</span><span class="p">]</span> <span class="o">=</span> <span class="n">host_arch</span>

<span class="c1"># FINAL TYPE: "s390x" | "arm64" | "arm" | "ia32" | "mipsel" | "mips" | "mips64el" | "ppc64" | "x64" | "riscv64" | "riscv32" | "loong64"
</span><span class="n">o</span><span class="p">[</span><span class="s">'variables'</span><span class="p">][</span><span class="s">'target_arch'</span><span class="p">]</span> <span class="o">=</span> <span class="n">target_arch</span>
</code></pre></div></div>
<p>So the final possible values for <code>process.arch</code> are the same as those possible for <code>NODE_ARCH</code> which are: <code>&quot;s390x&quot;</code>, <code>&quot;arm64&quot;</code>, <code>&quot;arm&quot;</code>, <code>&quot;ia32&quot;</code>, <code>&quot;mipsel&quot;</code>, <code>&quot;mips&quot;</code>, <code>&quot;mips64el&quot;</code>, <code>&quot;ppc64&quot;</code>, <code>&quot;x64&quot;</code>, <code>&quot;riscv64&quot;</code>, <code>&quot;riscv32&quot;</code>, <code>&quot;loong64&quot;</code>.</p>
<h2 id="codenodeoscode-codemachinecode"><code>node:os</code> <code>machine()</code></h2>
<p><code>os.machine()</code> is a wrapper that returns the <code>...[3]</code> property of the return value of <code>internalBinding(&quot;os&quot;).getOSInformation()</code>.</p>
<div><a href="https://github.com/nodejs/node/blob/4e1f39b678b37017ac9baa0971e3aeecd3b67b51/lib/os.js#L330"><code>lib/os.js</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
  <span class="c1">// -- ✂️ SNIP --</span>
  <span class="na">machine</span><span class="p">:</span> <span class="nx">getMachine</span><span class="p">,</span>
<span class="p">};</span>
</code></pre></div></div>
<div><a href="https://github.com/nodejs/node/blob/4e1f39b678b37017ac9baa0971e3aeecd3b67b51/lib/os.js#L100"><code>lib/os.js</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">getMachine</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">machine</span><span class="p">;</span>
</code></pre></div></div>
<div><a href="https://github.com/nodejs/node/blob/4e1f39b678b37017ac9baa0971e3aeecd3b67b51/lib/os.js#L77"><code>lib/os.js</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="p">{</span>
  <span class="mi">0</span><span class="p">:</span> <span class="nx">type</span><span class="p">,</span>
  <span class="mi">1</span><span class="p">:</span> <span class="nx">version</span><span class="p">,</span>
  <span class="mi">2</span><span class="p">:</span> <span class="nx">release</span><span class="p">,</span>
  <span class="mi">3</span><span class="p">:</span> <span class="nx">machine</span><span class="p">,</span>
<span class="p">}</span> <span class="o">=</span> <span class="nx">_getOSInformation</span><span class="p">();</span>
</code></pre></div></div>
<div><a href="https://github.com/nodejs/node/blob/4e1f39b678b37017ac9baa0971e3aeecd3b67b51/lib/os.js#L77"><code>lib/os.js</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="p">{</span>
  <span class="nx">getAvailableParallelism</span><span class="p">,</span>
  <span class="nx">getCPUs</span><span class="p">,</span>
  <span class="nx">getFreeMem</span><span class="p">,</span>
  <span class="na">getHomeDirectory</span><span class="p">:</span> <span class="nx">_getHomeDirectory</span><span class="p">,</span>
  <span class="na">getHostname</span><span class="p">:</span> <span class="nx">_getHostname</span><span class="p">,</span>
  <span class="na">getInterfaceAddresses</span><span class="p">:</span> <span class="nx">_getInterfaceAddresses</span><span class="p">,</span>
  <span class="nx">getLoadAvg</span><span class="p">,</span>
  <span class="na">getPriority</span><span class="p">:</span> <span class="nx">_getPriority</span><span class="p">,</span>
  <span class="na">getOSInformation</span><span class="p">:</span> <span class="nx">_getOSInformation</span><span class="p">,</span> <span class="c1">// 👈</span>
  <span class="nx">getTotalMem</span><span class="p">,</span>
  <span class="nx">getUserInfo</span><span class="p">,</span>
  <span class="na">getUptime</span><span class="p">:</span> <span class="nx">_getUptime</span><span class="p">,</span>
  <span class="nx">isBigEndian</span><span class="p">,</span>
  <span class="na">setPriority</span><span class="p">:</span> <span class="nx">_setPriority</span><span class="p">,</span>
<span class="p">}</span> <span class="o">=</span> <span class="nx">internalBinding</span><span class="p">(</span><span class="dl">'</span><span class="s1">os</span><span class="dl">'</span><span class="p">);</span>
</code></pre></div></div>
<p>That <code>getOSInformation()</code> C++ function sets <code>...[3]</code> to <code>info.machine</code> which is set by <code>uv_os_name()</code>.</p>
<div><a href="https://github.com/nodejs/node/blob/4e1f39b678b37017ac9baa0971e3aeecd3b67b51/src/node_os.cc#L82"><code>src/node_os.cc</code></a></div>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="kt">void</span> <span class="nf">GetOSInformation</span><span class="p">(</span><span class="k">const</span> <span class="n">FunctionCallbackInfo</span><span class="o">&lt;</span><span class="n">Value</span><span class="o">&gt;&amp;</span> <span class="n">args</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">Environment</span><span class="o">*</span> <span class="n">env</span> <span class="o">=</span> <span class="n">Environment</span><span class="o">::</span><span class="n">GetCurrent</span><span class="p">(</span><span class="n">args</span><span class="p">);</span>
  <span class="n">uv_utsname_t</span> <span class="n">info</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">err</span> <span class="o">=</span> <span class="n">uv_os_uname</span><span class="p">(</span><span class="o">&amp;</span><span class="n">info</span><span class="p">);</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">err</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">CHECK_GE</span><span class="p">(</span><span class="n">args</span><span class="p">.</span><span class="n">Length</span><span class="p">(),</span> <span class="mi">1</span><span class="p">);</span>
    <span class="n">USE</span><span class="p">(</span><span class="n">env</span><span class="o">-&gt;</span><span class="n">CollectUVExceptionInfo</span><span class="p">(</span>
        <span class="n">args</span><span class="p">[</span><span class="n">args</span><span class="p">.</span><span class="n">Length</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">],</span> <span class="n">err</span><span class="p">,</span> <span class="s">"uv_os_uname"</span><span class="p">));</span>
    <span class="k">return</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="c1">// [sysname, version, release, machine]</span>
  <span class="n">Local</span><span class="o">&lt;</span><span class="n">Value</span><span class="o">&gt;</span> <span class="n">osInformation</span><span class="p">[</span><span class="mi">4</span><span class="p">];</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">String</span><span class="o">::</span><span class="n">NewFromUtf8</span><span class="p">(</span><span class="n">env</span><span class="o">-&gt;</span><span class="n">isolate</span><span class="p">(),</span> <span class="n">info</span><span class="p">.</span><span class="n">sysname</span><span class="p">)</span>
          <span class="p">.</span><span class="n">ToLocal</span><span class="p">(</span><span class="o">&amp;</span><span class="n">osInformation</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">&amp;&amp;</span>
      <span class="n">String</span><span class="o">::</span><span class="n">NewFromUtf8</span><span class="p">(</span><span class="n">env</span><span class="o">-&gt;</span><span class="n">isolate</span><span class="p">(),</span> <span class="n">info</span><span class="p">.</span><span class="n">version</span><span class="p">)</span>
          <span class="p">.</span><span class="n">ToLocal</span><span class="p">(</span><span class="o">&amp;</span><span class="n">osInformation</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="o">&amp;&amp;</span>
      <span class="n">String</span><span class="o">::</span><span class="n">NewFromUtf8</span><span class="p">(</span><span class="n">env</span><span class="o">-&gt;</span><span class="n">isolate</span><span class="p">(),</span> <span class="n">info</span><span class="p">.</span><span class="n">release</span><span class="p">)</span>
          <span class="p">.</span><span class="n">ToLocal</span><span class="p">(</span><span class="o">&amp;</span><span class="n">osInformation</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="o">&amp;&amp;</span>
      <span class="n">String</span><span class="o">::</span><span class="n">NewFromUtf8</span><span class="p">(</span><span class="n">env</span><span class="o">-&gt;</span><span class="n">isolate</span><span class="p">(),</span> <span class="n">info</span><span class="p">.</span><span class="n">machine</span><span class="p">)</span> <span class="c1">// 👈</span>
          <span class="p">.</span><span class="n">ToLocal</span><span class="p">(</span><span class="o">&amp;</span><span class="n">osInformation</span><span class="p">[</span><span class="mi">3</span><span class="p">]))</span> <span class="p">{</span>
    <span class="n">args</span><span class="p">.</span><span class="n">GetReturnValue</span><span class="p">().</span><span class="n">Set</span><span class="p">(</span>
        <span class="n">Array</span><span class="o">::</span><span class="n">New</span><span class="p">(</span><span class="n">env</span><span class="o">-&gt;</span><span class="n">isolate</span><span class="p">(),</span> <span class="n">osInformation</span><span class="p">,</span> <span class="n">arraysize</span><span class="p">(</span><span class="n">osInformation</span><span class="p">)));</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p><code>uv_os_name()</code> has two different implementations: one for Unix and one for Windows. The Unix implementation uses <code>uname()</code> <code>.machine</code>.</p>
<div><a href="https://github.com/libuv/libuv/blob/ec7ec98b70149bafc2f8d57b9e4133e2f2570d52/src/unix/core.c#L1856">libuv/libuv: <code>src/unix/core.c</code></a></div>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">uv_os_uname</span><span class="p">(</span><span class="n">uv_utsname_t</span><span class="o">*</span> <span class="n">buffer</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">struct</span> <span class="nc">utsname</span> <span class="n">buf</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">r</span><span class="p">;</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">buffer</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">UV_EINVAL</span><span class="p">;</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">uname</span><span class="p">(</span><span class="o">&amp;</span><span class="n">buf</span><span class="p">)</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">r</span> <span class="o">=</span> <span class="n">UV__ERR</span><span class="p">(</span><span class="n">errno</span><span class="p">);</span>
    <span class="k">goto</span> <span class="n">error</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="c1">// -- ✂️ SNIP --</span>

<span class="cp">#if defined(_AIX) || defined(__PASE__)
</span>  <span class="n">r</span> <span class="o">=</span> <span class="n">uv__strscpy</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">,</span> <span class="s">"ppc64"</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">));</span>
<span class="cp">#else
</span>  <span class="n">r</span> <span class="o">=</span> <span class="n">uv__strscpy</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">,</span> <span class="n">buf</span><span class="p">.</span><span class="n">machine</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">));</span>
<span class="cp">#endif
</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">UV_E2BIG</span><span class="p">)</span>
    <span class="k">goto</span> <span class="n">error</span><span class="p">;</span>

  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>

<span class="nl">error:</span>
  <span class="n">buffer</span><span class="o">-&gt;</span><span class="n">sysname</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
  <span class="n">buffer</span><span class="o">-&gt;</span><span class="n">release</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
  <span class="n">buffer</span><span class="o">-&gt;</span><span class="n">version</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
  <span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
  <span class="k">return</span> <span class="n">r</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>So the possible values are <em>whatever <code>uname()</code> <code>.machine</code> can be</em> plus <code>ppc64</code> if it's AIX or <code>__PASE__</code> (whatever that is). But what are the possible values of <code>uname()</code> <code>.machine</code>? That's a good question... for another time. <sup>TODO: Investigate the possible values of <code>uname -m</code></sup></p>
<p><strong>Back to <code>uv_os_name()</code>.</strong> The Windows implementation sets the <code>.machine</code> property to a variety of static strings depending on some conditions.</p>
<div><a href="https://github.com/libuv/libuv/blob/ec7ec98b70149bafc2f8d57b9e4133e2f2570d52/src/win/util.c#L1676">libuv/libuv: <code>src/win/util.c</code></a></div>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">uv_os_uname</span><span class="p">(</span><span class="n">uv_utsname_t</span><span class="o">*</span> <span class="n">buffer</span><span class="p">)</span> <span class="p">{</span>
  <span class="cm">/* Implementation loosely based on
     https://github.com/gagern/gnulib/blob/master/lib/uname.c */</span>
  <span class="n">OSVERSIONINFOW</span> <span class="n">os_info</span><span class="p">;</span>
  <span class="n">SYSTEM_INFO</span> <span class="n">system_info</span><span class="p">;</span>
  <span class="n">HKEY</span> <span class="n">registry_key</span><span class="p">;</span>
  <span class="n">WCHAR</span> <span class="n">product_name_w</span><span class="p">[</span><span class="mi">256</span><span class="p">];</span>
  <span class="n">DWORD</span> <span class="n">product_name_w_size</span><span class="p">;</span>
  <span class="kt">size_t</span> <span class="n">version_size</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">processor_level</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">r</span><span class="p">;</span>

  <span class="c1">// -- ✂️ SNIP --</span>

  <span class="cm">/* Populate the machine field. */</span>
  <span class="n">GetSystemInfo</span><span class="p">(</span><span class="o">&amp;</span><span class="n">system_info</span><span class="p">);</span>

  <span class="k">switch</span> <span class="p">(</span><span class="n">system_info</span><span class="p">.</span><span class="n">wProcessorArchitecture</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">case</span> <span class="n">PROCESSOR_ARCHITECTURE_AMD64</span><span class="p">:</span>
      <span class="n">uv__strscpy</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">,</span> <span class="s">"x86_64"</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">));</span>
      <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">PROCESSOR_ARCHITECTURE_IA64</span><span class="p">:</span>
      <span class="n">uv__strscpy</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">,</span> <span class="s">"ia64"</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">));</span>
      <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">PROCESSOR_ARCHITECTURE_INTEL</span><span class="p">:</span>
      <span class="n">uv__strscpy</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">,</span> <span class="s">"i386"</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">));</span>

      <span class="k">if</span> <span class="p">(</span><span class="n">system_info</span><span class="p">.</span><span class="n">wProcessorLevel</span> <span class="o">&gt;</span> <span class="mi">3</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">processor_level</span> <span class="o">=</span> <span class="n">system_info</span><span class="p">.</span><span class="n">wProcessorLevel</span> <span class="o">&lt;</span> <span class="mi">6</span> <span class="o">?</span>
                          <span class="n">system_info</span><span class="p">.</span><span class="n">wProcessorLevel</span> <span class="o">:</span> <span class="mi">6</span><span class="p">;</span>
        <span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'0'</span> <span class="o">+</span> <span class="n">processor_level</span><span class="p">;</span>
      <span class="p">}</span>

      <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">PROCESSOR_ARCHITECTURE_IA32_ON_WIN64</span><span class="p">:</span>
      <span class="n">uv__strscpy</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">,</span> <span class="s">"i686"</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">));</span>
      <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">PROCESSOR_ARCHITECTURE_MIPS</span><span class="p">:</span>
      <span class="n">uv__strscpy</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">,</span> <span class="s">"mips"</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">));</span>
      <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">PROCESSOR_ARCHITECTURE_ALPHA</span><span class="p">:</span>
    <span class="k">case</span> <span class="n">PROCESSOR_ARCHITECTURE_ALPHA64</span><span class="p">:</span>
      <span class="n">uv__strscpy</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">,</span> <span class="s">"alpha"</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">));</span>
      <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">PROCESSOR_ARCHITECTURE_PPC</span><span class="p">:</span>
      <span class="n">uv__strscpy</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">,</span> <span class="s">"powerpc"</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">));</span>
      <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">PROCESSOR_ARCHITECTURE_SHX</span><span class="p">:</span>
      <span class="n">uv__strscpy</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">,</span> <span class="s">"sh"</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">));</span>
      <span class="k">break</span><span class="p">;</span>
    <span class="k">case</span> <span class="n">PROCESSOR_ARCHITECTURE_ARM</span><span class="p">:</span>
      <span class="n">uv__strscpy</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">,</span> <span class="s">"arm"</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">));</span>
      <span class="k">break</span><span class="p">;</span>
    <span class="nl">default:</span>
      <span class="n">uv__strscpy</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">,</span> <span class="s">"unknown"</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">));</span>
      <span class="k">break</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>

<span class="nl">error:</span>
  <span class="n">buffer</span><span class="o">-&gt;</span><span class="n">sysname</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
  <span class="n">buffer</span><span class="o">-&gt;</span><span class="n">release</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
  <span class="n">buffer</span><span class="o">-&gt;</span><span class="n">version</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
  <span class="n">buffer</span><span class="o">-&gt;</span><span class="n">machine</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
  <span class="k">return</span> <span class="n">r</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>All possible values are: <code>x86_64</code>, <code>ia64</code>, <code>i386</code>, <code>i486</code>, <code>i586</code>, <code>i686</code>, <code>mips</code>, <code>alpha</code>, <code>powerpc</code>, <code>sh</code>, <code>arm</code>, <code>unknown</code>.</p>
<p>So the possible values are well-known on Windows (yay), but very varied on Unix systems (not yay). This post is already too long; I'm not going to investigate all <code>uname -m</code> possible values, too. Maybe another time.</p>]]></content><author><name>Jacob Hummer</name><email>jcbhmr@outlook.com</email></author><summary type="html"><![CDATA[The official Node.js docs (v25.2.1) say that process.platform can be 'aix' | 'darwin' | 'freebsd' | 'linux' | 'openbsd' | 'sunos' | 'win32' and process.arch can be 'arm' | 'arm64' | 'ia32' | 'loong64' | 'mips' | 'mipsel' | 'ppc64' | 'riscv64' | 's390' | 's390x' | 'x64'. That's not quite true. This is my chronicle as I explore where the values come from.]]></summary></entry><entry><title type="html">Possible platform/arch names in Deno.build &amp;amp; node:process</title><link href="https://jcbhmr.com/2025/12/14/deno-build-possible-values/" rel="alternate" type="text/html" title="Possible platform/arch names in Deno.build &amp;amp; node:process" /><published>2025-12-14T00:00:00+00:00</published><updated>2025-12-14T00:00:00+00:00</updated><id>https://jcbhmr.com/2025/12/14/deno-build-possible-values</id><content type="html" xml:base="https://jcbhmr.com/2025/12/14/deno-build-possible-values/"><![CDATA[<p>I did some diving into what the possible values for these string enums are:</p>
<ul>
<li><a href="https://docs.deno.com/api/deno/~/Deno.build.os"><code>Deno.build.os</code></a></li>
<li><a href="https://docs.deno.com/api/deno/~/Deno.build.arch"><code>Deno.build.arch</code></a></li>
<li><a href="https://docs.deno.com/api/deno/~/Deno.build.target"><code>Deno.build.target</code></a></li>
<li><a href="https://docs.deno.com/api/node/process/~/Process#property_platform"><code>node:process</code> <code>platform</code></a> &amp; <a href="https://docs.deno.com/api/node/os/~/platform"><code>node:os</code> <code>platform()</code></a></li>
<li><a href="https://docs.deno.com/api/node/process/~/Process#property_arch"><code>node:process</code> <code>arch</code></a> &amp; <a href="https://docs.deno.com/api/node/os/~/arch"><code>node:os</code> <code>arch()</code></a></li>
<li><a href="https://docs.deno.com/api/node/os/~/machine"><code>node:os</code> <code>machine()</code></a></li>
</ul>
<p>Note that the <code>node:</code>-related values that I'm discussing are <strong>for Deno's Node.js API polyfills</strong>, not the Node.js' implementation of them. That's another deep dive that I might explore later. <strong>This is just Deno's platform/arch values</strong> -- where and how they are exposed to JS code.</p>
<p><strong>TL;DR:</strong></p>
<ul>
<li><code>Deno.build.os</code> is <a href="https://docs.rs/platforms/latest/platforms/target/enum.OS.html">any possible OS name across all valid Rust targets</a></li>
<li><code>Deno.build.arch</code> is <a href="https://docs.rs/platforms/latest/platforms/target/enum.Arch.html">any possible arch name across all valid Rust targets</a></li>
<li><code>Deno.build.target</code> is <a href="https://doc.rust-lang.org/stable/rustc/targets/built-in.html">any valid Rust target tuple</a></li>
<li><code>process.platform</code> is <a href="https://docs.rs/platforms/latest/platforms/target/enum.OS.html">any possible OS name across all valid Rust targets</a> <strong>but replace <code>windows</code> with <code>win32</code></strong></li>
<li><code>process.arch</code> is <code>&quot;x64&quot; | &quot;arm64&quot; | &quot;riscv64&quot;</code> <strong>only</strong>; it throws an <code>Error</code> when run on any other arch</li>
<li><code>os.machine()</code> is <a href="https://docs.rs/platforms/latest/platforms/target/enum.Arch.html">any possible arch name across all valid Rust targets</a> <strong>but replace <code>aarch64</code> with <code>arm64</code></strong></li>
</ul>
<p>⚠️ <strong>Remember!</strong> These are the possible values <em>for Deno's Node.js <code>node:</code> polyfills</em>, not for Node.js' own implementation.</p>
<h2 id="codedenobuildcode"><code>Deno.build</code></h2>
<p>There's this <code>Deno.build</code> object. It's configured with default values.</p>
<div><a href="https://github.com/denoland/deno_core/blob/2898ad965ab1b5c616c9b6738b0b7ae046653320/core/00_infra.js#L58">denoland/deno: <code>core/00_infra.js</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">build</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">target</span><span class="p">:</span> <span class="dl">"</span><span class="s2">unknown</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">arch</span><span class="p">:</span> <span class="dl">"</span><span class="s2">unknown</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">os</span><span class="p">:</span> <span class="dl">"</span><span class="s2">unknown</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">vendor</span><span class="p">:</span> <span class="dl">"</span><span class="s2">unknown</span><span class="dl">"</span><span class="p">,</span>
  <span class="na">env</span><span class="p">:</span> <span class="kc">undefined</span><span class="p">,</span>
<span class="p">};</span>
</code></pre></div></div>
<p>There's a <code>setBuildInfo()</code> function...</p>
<div><a href="https://github.com/denoland/deno_core/blob/2898ad965ab1b5c616c9b6738b0b7ae046653320/core/00_infra.js#L66">denoland/deno_core: <code>core/00_infra.js</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">setBuildInfo</span><span class="p">(</span><span class="nx">target</span><span class="p">)</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="p">{</span> <span class="mi">0</span><span class="p">:</span> <span class="nx">arch</span><span class="p">,</span> <span class="mi">1</span><span class="p">:</span> <span class="nx">vendor</span><span class="p">,</span> <span class="mi">2</span><span class="p">:</span> <span class="nx">os</span><span class="p">,</span> <span class="mi">3</span><span class="p">:</span> <span class="nx">env</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">StringPrototypeSplit</span><span class="p">(</span>
    <span class="nx">target</span><span class="p">,</span>
    <span class="dl">"</span><span class="s2">-</span><span class="dl">"</span><span class="p">,</span>
    <span class="mi">4</span><span class="p">,</span>
  <span class="p">);</span>
  <span class="nx">build</span><span class="p">.</span><span class="nx">target</span> <span class="o">=</span> <span class="nx">target</span><span class="p">;</span>
  <span class="nx">build</span><span class="p">.</span><span class="nx">arch</span> <span class="o">=</span> <span class="nx">arch</span><span class="p">;</span>
  <span class="nx">build</span><span class="p">.</span><span class="nx">vendor</span> <span class="o">=</span> <span class="nx">vendor</span><span class="p">;</span>
  <span class="nx">build</span><span class="p">.</span><span class="nx">os</span> <span class="o">=</span> <span class="nx">os</span><span class="p">;</span>
  <span class="nx">build</span><span class="p">.</span><span class="nx">env</span> <span class="o">=</span> <span class="nx">env</span><span class="p">;</span>
  <span class="nx">ObjectFreeze</span><span class="p">(</span><span class="nx">build</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>...which is exposed as <code>Deno.core.setBuildInfo()</code>.</p>
<div><a href="https://github.com/denoland/deno_core/blob/2898ad965ab1b5c616c9b6738b0b7ae046653320/core/00_infra.js#L432">denoland/deno_core: <code>core/00_infra.js</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Extra Deno.core.* exports</span>
<span class="kd">const</span> <span class="nx">core</span> <span class="o">=</span> <span class="nx">ObjectAssign</span><span class="p">(</span><span class="nx">globalThis</span><span class="p">.</span><span class="nx">Deno</span><span class="p">.</span><span class="nx">core</span><span class="p">,</span> <span class="p">{</span>
  <span class="nx">build</span><span class="p">,</span>
  <span class="nx">setBuildInfo</span><span class="p">,</span> <span class="c1">// 👈</span>
  <span class="nx">registerErrorBuilder</span><span class="p">,</span>
  <span class="nx">buildCustomError</span><span class="p">,</span>
  <span class="nx">registerErrorClass</span><span class="p">,</span>
  <span class="nx">setUpAsyncStub</span><span class="p">,</span>
  <span class="nx">hasPromise</span><span class="p">,</span>
  <span class="nx">promiseIdSymbol</span><span class="p">,</span>
<span class="p">});</span>
</code></pre></div></div>
<p>Since this function is now exposed, it can be called from elsewhere.</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/runtime/js/99_main.js#L408">denoland/deno: <code>runtime/js/99_main.js</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">runtimeStart</span><span class="p">(</span>
  <span class="nx">denoVersion</span><span class="p">,</span>
  <span class="nx">v8Version</span><span class="p">,</span>
  <span class="nx">tsVersion</span><span class="p">,</span>
  <span class="nx">target</span><span class="p">,</span>
<span class="p">)</span> <span class="p">{</span>
  <span class="nx">core</span><span class="p">.</span><span class="nx">setWasmStreamingCallback</span><span class="p">(</span><span class="nx">fetch</span><span class="p">.</span><span class="nx">handleWasmStreaming</span><span class="p">);</span>
  <span class="nx">core</span><span class="p">.</span><span class="nx">setReportExceptionCallback</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">reportException</span><span class="p">);</span>
  <span class="nx">op_set_format_exception_callback</span><span class="p">(</span><span class="nx">formatException</span><span class="p">);</span>
  <span class="nx">version</span><span class="p">.</span><span class="nx">setVersions</span><span class="p">(</span>
    <span class="nx">denoVersion</span><span class="p">,</span>
    <span class="nx">v8Version</span><span class="p">,</span>
    <span class="nx">tsVersion</span><span class="p">,</span>
  <span class="p">);</span>
  <span class="nx">core</span><span class="p">.</span><span class="nx">setBuildInfo</span><span class="p">(</span><span class="nx">target</span><span class="p">);</span> <span class="c1">// 👈</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Where does this <code>runtimeStart()</code> function get called? In the same file.</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/runtime/js/99_main.js#L765">denoland/deno: <code>runtime/js/99_main.js</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">runtimeStart</span><span class="p">(</span>
  <span class="nx">denoVersion</span><span class="p">,</span>
  <span class="nx">v8Version</span><span class="p">,</span>
  <span class="nx">tsVersion</span><span class="p">,</span>
  <span class="nx">target</span><span class="p">,</span>
<span class="p">);</span>
</code></pre></div></div>
<p>But where does that <code>target</code> variable come from? <code>op_snapshot_options()</code>.</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/runtime/js/99_main.js#L604">denoland/deno: <code>runtime/js/99_main.js</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="p">{</span>
  <span class="nx">tsVersion</span><span class="p">,</span>
  <span class="nx">v8Version</span><span class="p">,</span>
  <span class="nx">target</span><span class="p">,</span>
<span class="p">}</span> <span class="o">=</span> <span class="nx">op_snapshot_options</span><span class="p">();</span>
</code></pre></div></div>
<p>But where does <em>that</em> come from? It's imported from <code>ext:core/ops</code>...</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/runtime/js/99_main.js#L21">denoland/deno: <code>runtime/js/99_main.js</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">{</span>
  <span class="nx">op_bootstrap_args</span><span class="p">,</span>
  <span class="nx">op_bootstrap_is_from_unconfigured_runtime</span><span class="p">,</span>
  <span class="nx">op_bootstrap_no_color</span><span class="p">,</span>
  <span class="nx">op_bootstrap_pid</span><span class="p">,</span>
  <span class="nx">op_bootstrap_stderr_no_color</span><span class="p">,</span>
  <span class="nx">op_bootstrap_stdout_no_color</span><span class="p">,</span>
  <span class="nx">op_get_ext_import_meta_proto</span><span class="p">,</span>
  <span class="nx">op_internal_log</span><span class="p">,</span>
  <span class="nx">op_main_module</span><span class="p">,</span>
  <span class="nx">op_ppid</span><span class="p">,</span>
  <span class="nx">op_set_format_exception_callback</span><span class="p">,</span>
  <span class="nx">op_snapshot_options</span><span class="p">,</span> <span class="c1">// 👈</span>
  <span class="nx">op_worker_close</span><span class="p">,</span>
  <span class="nx">op_worker_get_type</span><span class="p">,</span>
  <span class="nx">op_worker_post_message</span><span class="p">,</span>
  <span class="nx">op_worker_recv_message</span><span class="p">,</span>
  <span class="nx">op_worker_sync_fetch</span><span class="p">,</span>
<span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">ext:core/ops</span><span class="dl">"</span><span class="p">;</span>
</code></pre></div></div>
<p>...which is defined in <code>deno_core</code>.</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/runtime/ops/bootstrap.rs#L71">denoland/deno: <code>runtime/ops/bootstrap.rs</code></a></div>
<div class="language-rs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Note: Called at snapshot time, op perf is not a concern.</span>
<span class="nd">#[op2]</span>
<span class="nd">#[serde]</span>
<span class="k">pub</span> <span class="k">fn</span> <span class="nf">op_snapshot_options</span><span class="p">(</span><span class="n">state</span><span class="p">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">OpState</span><span class="p">)</span> <span class="k">-&gt;</span> <span class="n">SnapshotOptions</span> <span class="p">{</span>
  <span class="nd">#[cfg(feature</span> <span class="nd">=</span> <span class="s">"hmr"</span><span class="nd">)]</span>
  <span class="p">{</span>
    <span class="n">state</span><span class="py">.try_take</span><span class="p">::</span><span class="o">&lt;</span><span class="n">SnapshotOptions</span><span class="o">&gt;</span><span class="p">()</span><span class="nf">.unwrap_or_default</span><span class="p">()</span>
  <span class="p">}</span>
  <span class="nd">#[cfg(not(feature</span> <span class="nd">=</span> <span class="s">"hmr"</span><span class="nd">))]</span>
  <span class="p">{</span>
    <span class="n">state</span><span class="py">.take</span><span class="p">::</span><span class="o">&lt;</span><span class="n">SnapshotOptions</span><span class="o">&gt;</span><span class="p">()</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>But what's that <code>SnapshotOptions</code>?</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/runtime/ops/bootstrap.rs#L41">denoland/deno: <code>runtime/ops/bootstrap.rs</code></a></div>
<div class="language-rs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">#[derive(Serialize)]</span>
<span class="nd">#[serde(rename_all</span> <span class="nd">=</span> <span class="s">"camelCase"</span><span class="nd">)]</span>
<span class="k">pub</span> <span class="k">struct</span> <span class="n">SnapshotOptions</span> <span class="p">{</span>
  <span class="k">pub</span> <span class="n">ts_version</span><span class="p">:</span> <span class="nb">String</span><span class="p">,</span>
  <span class="k">pub</span> <span class="n">v8_version</span><span class="p">:</span> <span class="o">&amp;</span><span class="k">'static</span> <span class="nb">str</span><span class="p">,</span>
  <span class="k">pub</span> <span class="n">target</span><span class="p">:</span> <span class="nb">String</span><span class="p">,</span> <span class="c1">// 👈</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Where does the actual <code>target</code> string come from? Before we get to the <code>Default</code> implementation for <code>SnapshotOptions</code>, let's look at where else it's constructed. There's a manifest-like extension definition macro that defines a <code>deno_bootstrap</code> extension. It takes in a <code>SnapshotOptions</code> struct.</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/runtime/ops/bootstrap.rs#L33">denoland/deno: <code>runtime/ops/bootstrap.rs</code></a></div>
<div class="language-rs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">deno_core</span><span class="p">::</span><span class="nd">extension!</span><span class="p">(</span>
  <span class="n">deno_bootstrap</span><span class="p">,</span>
  <span class="n">ops</span> <span class="o">=</span> <span class="p">[</span>
    <span class="n">op_bootstrap_args</span><span class="p">,</span>
    <span class="n">op_bootstrap_pid</span><span class="p">,</span>
    <span class="n">op_bootstrap_numcpus</span><span class="p">,</span>
    <span class="n">op_bootstrap_user_agent</span><span class="p">,</span>
    <span class="n">op_bootstrap_language</span><span class="p">,</span>
    <span class="n">op_bootstrap_log_level</span><span class="p">,</span>
    <span class="n">op_bootstrap_color_depth</span><span class="p">,</span>
    <span class="n">op_bootstrap_no_color</span><span class="p">,</span>
    <span class="n">op_bootstrap_stdout_no_color</span><span class="p">,</span>
    <span class="n">op_bootstrap_stderr_no_color</span><span class="p">,</span>
    <span class="n">op_bootstrap_unstable_args</span><span class="p">,</span>
    <span class="n">op_bootstrap_is_from_unconfigured_runtime</span><span class="p">,</span>
    <span class="n">op_snapshot_options</span><span class="p">,</span>
  <span class="p">],</span>
  <span class="n">options</span> <span class="o">=</span> <span class="p">{</span>
    <span class="n">snapshot_options</span><span class="p">:</span> <span class="nb">Option</span><span class="o">&lt;</span><span class="n">SnapshotOptions</span><span class="o">&gt;</span><span class="p">,</span> <span class="c1">// 👈</span>
    <span class="n">is_from_unconfigured_runtime</span><span class="p">:</span> <span class="nb">bool</span><span class="p">,</span>
  <span class="p">},</span>
  <span class="n">state</span> <span class="o">=</span> <span class="p">|</span><span class="n">state</span><span class="p">,</span> <span class="n">options</span><span class="p">|</span> <span class="p">{</span>
    <span class="k">if</span> <span class="k">let</span> <span class="nf">Some</span><span class="p">(</span><span class="n">snapshot_options</span><span class="p">)</span> <span class="o">=</span> <span class="n">options</span><span class="py">.snapshot_options</span> <span class="p">{</span>
      <span class="n">state</span><span class="py">.put</span><span class="p">::</span><span class="o">&lt;</span><span class="n">SnapshotOptions</span><span class="o">&gt;</span><span class="p">(</span><span class="n">snapshot_options</span><span class="p">);</span> <span class="c1">// 👈</span>
    <span class="p">}</span>
    <span class="n">state</span><span class="nf">.put</span><span class="p">(</span><span class="nf">IsFromUnconfiguredRuntime</span><span class="p">(</span><span class="n">options</span><span class="py">.is_from_unconfigured_runtime</span><span class="p">));</span>
  <span class="p">},</span>
<span class="p">);</span>
</code></pre></div></div>
<p>I'll be honest, I don't know what the type of <code>state</code> is or what its lifecycle is. Somehow, though, <code>state</code> must be populated with a <code>SnapshotOptions</code> since it gets <code>.take()</code>-en in the <code>op_snapshot_options()</code> function above (sometimes with a default value via <code>.unwrap_or_default()</code>). But where does this extension get initialized with a <code>SnapshotOptions</code> struct? In the <code>common_extensions()</code> convenience function that initializes and returns a bunch of -- you guessed it -- common extensions.</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/runtime/worker.rs#L1076">denoland/deno: <code>runtime/worker.rs</code></a></div>
<div class="language-rs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">fn</span> <span class="n">common_extensions</span><span class="o">&lt;</span>
  <span class="n">TInNpmPackageChecker</span><span class="p">:</span> <span class="n">InNpmPackageChecker</span> <span class="o">+</span> <span class="k">'static</span><span class="p">,</span>
  <span class="n">TNpmPackageFolderResolver</span><span class="p">:</span> <span class="n">NpmPackageFolderResolver</span> <span class="o">+</span> <span class="k">'static</span><span class="p">,</span>
  <span class="n">TExtNodeSys</span><span class="p">:</span> <span class="n">ExtNodeSys</span> <span class="o">+</span> <span class="k">'static</span><span class="p">,</span>
<span class="o">&gt;</span><span class="p">(</span>
  <span class="n">has_snapshot</span><span class="p">:</span> <span class="nb">bool</span><span class="p">,</span>
  <span class="n">unconfigured_runtime</span><span class="p">:</span> <span class="nb">bool</span><span class="p">,</span>
<span class="p">)</span> <span class="k">-&gt;</span> <span class="nb">Vec</span><span class="o">&lt;</span><span class="n">Extension</span><span class="o">&gt;</span> <span class="p">{</span>
  <span class="c1">// NOTE(bartlomieju): ordering is important here, keep it in sync with</span>
  <span class="c1">// `runtime/worker.rs`, `runtime/web_worker.rs`, `runtime/snapshot_info.rs`</span>
  <span class="c1">// and `runtime/snapshot.rs`!</span>
  <span class="nd">vec!</span><span class="p">[</span>
    <span class="c1">// -- ✂️ SNIP --</span>
    <span class="nn">ops</span><span class="p">::</span><span class="nn">bootstrap</span><span class="p">::</span><span class="nn">deno_bootstrap</span><span class="p">::</span><span class="nf">init</span><span class="p">(</span>
      <span class="n">has_snapshot</span><span class="nf">.then</span><span class="p">(</span><span class="nn">Default</span><span class="p">::</span><span class="n">default</span><span class="p">),</span> <span class="c1">// 👈</span>
      <span class="n">unconfigured_runtime</span><span class="p">,</span>
    <span class="p">),</span>
    <span class="c1">// -- ✂️ SNIP --</span>
  <span class="p">]</span>
<span class="p">}</span>
</code></pre></div></div>
<p>There's also this snapshotting thing that seems to happen at build time, which probably magically bakes in the snapshot options somehow? I'm not really sure. All I know is that these options are somehow stashed and retrieved by the Deno runtime. 🤷</p>
<div><a href="https://github.com/denoland/deno/blob/main/cli/snapshot/build.rs#L22">denoland/deno: <code>cli/snapshot/build.rs</code></a></div>
<div class="language-rs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">snapshot_options</span> <span class="o">=</span> <span class="n">SnapshotOptions</span> <span class="p">{</span>
  <span class="n">ts_version</span><span class="p">:</span> <span class="nn">shared</span><span class="p">::</span><span class="n">TS_VERSION</span><span class="nf">.to_string</span><span class="p">(),</span>
  <span class="n">v8_version</span><span class="p">:</span> <span class="nn">deno_runtime</span><span class="p">::</span><span class="nn">deno_core</span><span class="p">::</span><span class="nn">v8</span><span class="p">::</span><span class="n">VERSION_STRING</span><span class="p">,</span>
  <span class="n">target</span><span class="p">:</span> <span class="nn">std</span><span class="p">::</span><span class="nn">env</span><span class="p">::</span><span class="nf">var</span><span class="p">(</span><span class="s">"TARGET"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">(),</span>
<span class="p">};</span>
</code></pre></div></div>
<p>There's also the default implementation, which uses the Rust-provided compile-time OS/arch constants to reconstruct the likely target triple string.</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/runtime/ops/bootstrap.rs#L53">denoland/deno: <code>runtime/ops/bootstrap.rs</code></a></div>
<div class="language-rs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">impl</span> <span class="nb">Default</span> <span class="k">for</span> <span class="n">SnapshotOptions</span> <span class="p">{</span>
  <span class="k">fn</span> <span class="nf">default</span><span class="p">()</span> <span class="k">-&gt;</span> <span class="k">Self</span> <span class="p">{</span>
    <span class="k">let</span> <span class="n">arch</span> <span class="o">=</span> <span class="nn">std</span><span class="p">::</span><span class="nn">env</span><span class="p">::</span><span class="nn">consts</span><span class="p">::</span><span class="n">ARCH</span><span class="p">;</span>
    <span class="k">let</span> <span class="n">platform</span> <span class="o">=</span> <span class="nn">std</span><span class="p">::</span><span class="nn">env</span><span class="p">::</span><span class="nn">consts</span><span class="p">::</span><span class="n">OS</span><span class="p">;</span>
    <span class="k">let</span> <span class="n">target</span> <span class="o">=</span> <span class="k">match</span> <span class="n">platform</span> <span class="p">{</span>
      <span class="s">"macos"</span> <span class="k">=&gt;</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{}-apple-darwin"</span><span class="p">,</span> <span class="n">arch</span><span class="p">),</span>
      <span class="s">"linux"</span> <span class="k">=&gt;</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{}-unknown-linux-gnu"</span><span class="p">,</span> <span class="n">arch</span><span class="p">),</span>
      <span class="s">"windows"</span> <span class="k">=&gt;</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{}-pc-windows-msvc"</span><span class="p">,</span> <span class="n">arch</span><span class="p">),</span>
      <span class="n">rest</span> <span class="k">=&gt;</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{}-{}"</span><span class="p">,</span> <span class="n">arch</span><span class="p">,</span> <span class="n">rest</span><span class="p">),</span>
    <span class="p">};</span>

    <span class="k">Self</span> <span class="p">{</span>
      <span class="n">ts_version</span><span class="p">:</span> <span class="s">"n/a"</span><span class="nf">.to_owned</span><span class="p">(),</span>
      <span class="n">v8_version</span><span class="p">:</span> <span class="nn">deno_core</span><span class="p">::</span><span class="nn">v8</span><span class="p">::</span><span class="n">VERSION_STRING</span><span class="p">,</span>
      <span class="n">target</span><span class="p">,</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>So that <code>Deno.build.target</code> value (which is obtained from Rust via <code>op_snapshot_options()</code>) is what the rest of the <code>Deno.build</code> object's properties are based on. It's is either passed in at build time via snapshotting or reconstructed from the Rust-provided information at runtime.</p>
<div class="language-rs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">target</span> <span class="o">=</span> <span class="nn">std</span><span class="p">::</span><span class="nn">env</span><span class="p">::</span><span class="nf">var</span><span class="p">(</span><span class="s">"TARGET"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
</code></pre></div></div>
<div class="language-rs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">target</span> <span class="o">=</span> <span class="k">match</span> <span class="nn">std</span><span class="p">::</span><span class="nn">env</span><span class="p">::</span><span class="nn">consts</span><span class="p">::</span><span class="n">OS</span> <span class="p">{</span>
  <span class="s">"macos"</span> <span class="k">=&gt;</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{}-apple-darwin"</span><span class="p">,</span> <span class="nn">std</span><span class="p">::</span><span class="nn">env</span><span class="p">::</span><span class="nn">consts</span><span class="p">::</span><span class="n">ARCH</span><span class="p">),</span>
  <span class="s">"linux"</span> <span class="k">=&gt;</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{}-unknown-linux-gnu"</span><span class="p">,</span> <span class="nn">std</span><span class="p">::</span><span class="nn">env</span><span class="p">::</span><span class="nn">consts</span><span class="p">::</span><span class="n">ARCH</span><span class="p">),</span>
  <span class="s">"windows"</span> <span class="k">=&gt;</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{}-pc-windows-msvc"</span><span class="p">,</span> <span class="nn">std</span><span class="p">::</span><span class="nn">env</span><span class="p">::</span><span class="nn">consts</span><span class="p">::</span><span class="n">ARCH</span><span class="p">),</span>
  <span class="n">rest</span> <span class="k">=&gt;</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{}-{}"</span><span class="p">,</span> <span class="nn">std</span><span class="p">::</span><span class="nn">env</span><span class="p">::</span><span class="nn">consts</span><span class="p">::</span><span class="n">ARCH</span><span class="p">,</span> <span class="n">rest</span><span class="p">),</span>
<span class="p">};</span>
</code></pre></div></div>
<p>So that's <a href="https://doc.rust-lang.org/stable/rustc/targets/built-in.html">every Rust target tuple</a> that Deno happens to successfully compile on. I don't know how long a list that is.</p>
<p>The <a href="https://github.com/denoland/deno/releases/tag/v2.6.0">targets that Deno provides official releases for (as of Deno v2.6.0)</a> are:</p>
<ul>
<li><code>aarch64-apple-darwin</code></li>
<li><code>aarch64-unknown-linux-gnu</code></li>
<li><code>x86_64-apple-darwin</code></li>
<li><code>x86_64-pc-windows-msvc</code></li>
<li><code>x86_64-unknown-linux-gnu</code></li>
</ul>
<h3 id="codedenobuildoscode"><code>Deno.build.os</code></h3>
<p>So the final verdict is that <code>Deno.build.os</code> is derived from the third component of a <code>&lt;arch&gt;-&lt;vendor&gt;-&lt;os&gt;-&lt;env&gt;</code> target tuple which means that <strong><code>Deno.build.os</code> would be <code>darwin</code>, <code>linux</code>, or <code>windows</code></strong> unless <strong>Deno is compiled for another target</strong> (which is possible). <a href="https://docs.deno.com/api/deno/~/Deno.build.os">The official Deno docs for <code>Deno.build.os</code></a> state that its type is <code>&quot;darwin&quot; | &quot;linux&quot; | &quot;android&quot; | &quot;windows&quot; | &quot;freebsd&quot; | &quot;netbsd&quot; | &quot;aix&quot; | &quot;solaris&quot; | &quot;illumos&quot;</code>.</p>
<h3 id="codedenobuildarchcode"><code>Deno.build.arch</code></h3>
<p>The <code>Deno.build.arch</code> value is a similar story. Given the official targets, the first <code>arch</code> component can be <strong>either <code>aarch64</code> or <code>x86_64</code></strong>. Other architectures like <code>riscv64gc</code> might successfully compile for all I know. The docs say that <code>Deno.build.arch</code>'s type is <code>&quot;aarch64&quot; | &quot;x86_64&quot;</code>.</p>
<h3 id="codenodeprocesscode-codeplatformcode-amp-codenodeoscode-codeplatformcode"><code>node:process</code> <code>platform</code> &amp; <code>node:os</code> <code>platform()</code></h3>
<p>Deno's <code>node:os</code> <code>platform()</code> function is just a wrapper around <code>process.platform</code>.</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/ext/node/polyfills/os.ts#L241">denoland/deno: <code>ext/node/polyfills/os.ts</code></a></div>
<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/** Returns the a string identifying the operating system platform. The value is set at compile time. Possible values are 'darwin', 'linux', and 'win32'. */</span>
<span class="k">export</span> <span class="kd">function</span> <span class="nx">platform</span><span class="p">():</span> <span class="kr">string</span> <span class="p">{</span>
  <span class="k">return</span> <span class="nx">process</span><span class="p">.</span><span class="nx">platform</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Deno's <code>node:process</code> <code>platform</code> (or <code>process.platform</code>) is a variable...</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/ext/node/polyfills/process.ts#L82">denoland/deno: <code>ext/node/polyfills/process.ts</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">export</span> <span class="kd">let</span> <span class="nx">platform</span> <span class="o">=</span> <span class="nx">isWindows</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">win32</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">""</span><span class="p">;</span> <span class="c1">// initialized during bootstrap</span>
</code></pre></div></div>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/ext/node/polyfills/process.ts#L748">denoland/deno: <code>ext/node/polyfills/process.ts</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/** https://nodejs.org/api/process.html#process_process_platform */</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">defineProperty</span><span class="p">(</span><span class="nx">process</span><span class="p">,</span> <span class="dl">"</span><span class="s2">platform</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span>
  <span class="kd">get</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">platform</span><span class="p">;</span>
  <span class="p">},</span>
<span class="p">});</span>
</code></pre></div></div>
<p>...that's initialized at bootstrapping time to the value of <code>Deno.build.os</code>. Unless <code>isWindows</code> is true; then it's set to <code>win32</code> (<strong>not</strong> <code>windows</code>).</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/ext/node/polyfills/process.ts#L1077">denoland/deno: <code>ext/node/polyfills/process.ts</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Should be called only once, in `runtime/js/99_main.js` when the runtime is</span>
<span class="c1">// bootstrapped.</span>
<span class="nx">internals</span><span class="p">.</span><span class="nx">__bootstrapNodeProcess</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span>
  <span class="nx">argv0Val</span><span class="p">:</span> <span class="nx">string</span> <span class="o">|</span> <span class="kc">undefined</span><span class="p">,</span>
  <span class="nx">args</span><span class="p">:</span> <span class="nx">string</span><span class="p">[],</span>
  <span class="nx">denoVersions</span><span class="p">:</span> <span class="nx">Record</span><span class="o">&lt;</span><span class="nx">string</span><span class="p">,</span> <span class="nx">string</span><span class="o">&gt;</span><span class="p">,</span>
  <span class="nx">nodeDebug</span><span class="p">:</span> <span class="nx">string</span><span class="p">,</span>
  <span class="nx">warmup</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span>
<span class="p">)</span> <span class="p">{</span>
    <span class="c1">// -- ✂️ SNIP --</span>
    <span class="nx">arch</span> <span class="o">=</span> <span class="nx">arch_</span><span class="p">();</span>
    <span class="nx">platform</span> <span class="o">=</span> <span class="nx">isWindows</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">win32</span><span class="dl">"</span> <span class="p">:</span> <span class="nx">Deno</span><span class="p">.</span><span class="nx">build</span><span class="p">.</span><span class="nx">os</span><span class="p">;</span> <span class="c1">// 👈</span>
    <span class="nx">pid</span> <span class="o">=</span> <span class="nx">Deno</span><span class="p">.</span><span class="nx">pid</span><span class="p">;</span>
    <span class="nx">ppid</span> <span class="o">=</span> <span class="nx">Deno</span><span class="p">.</span><span class="nx">ppid</span><span class="p">;</span>
    <span class="nx">initializeDebugEnv</span><span class="p">(</span><span class="nx">nodeDebug</span><span class="p">);</span>
    <span class="c1">// -- ✂️ SNIP --</span>
<span class="p">};</span>
</code></pre></div></div>
<p>So what's this <code>isWindows</code> thing? It's pretty self-explanatory, but let's investigate anyway.</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/ext/node/polyfills/process.ts#L74">denoland/deno: <code>ext/node/polyfills/process.ts</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">{</span> <span class="nx">isAndroid</span><span class="p">,</span> <span class="nx">isWindows</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">ext:deno_node/_util/os.ts</span><span class="dl">"</span><span class="p">;</span>
</code></pre></div></div>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/ext/node/polyfills/_util/os.ts">denoland/deno: <code>ext/node/polyfills/_util/os.ts</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// -- Some parts ✂️snipped for brevity --</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">op_node_build_os</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">ext:core/ops</span><span class="dl">"</span><span class="p">;</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">osType</span><span class="p">:</span> <span class="nx">OSType</span> <span class="o">=</span> <span class="nx">op_node_build_os</span><span class="p">();</span>
<span class="k">export</span> <span class="kd">const</span> <span class="nx">isWindows</span> <span class="o">=</span> <span class="nx">osType</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">windows</span><span class="dl">"</span><span class="p">;</span>
</code></pre></div></div>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/ext/node/lib.rs#L93">denoland/deno: <code>ext/node/lib.rs</code></a></div>
<div class="language-rs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">#[op2]</span>
<span class="nd">#[string]</span>
<span class="k">fn</span> <span class="nf">op_node_build_os</span><span class="p">()</span> <span class="k">-&gt;</span> <span class="nb">String</span> <span class="p">{</span>
  <span class="nd">env!</span><span class="p">(</span><span class="s">"TARGET"</span><span class="p">)</span><span class="nf">.split</span><span class="p">(</span><span class="sc">'-'</span><span class="p">)</span><span class="nf">.nth</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">()</span><span class="nf">.to_string</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div></div>
<p>A Rust <code>TARGET</code> string is <code>&lt;arch&gt;-&lt;vendor&gt;-&lt;os&gt;-&lt;env&gt;</code>. <code>op_node_build_os()</code> just returns the <code>os</code> part of that tuple. It seems like it's the same value as <code>Deno.build.os</code>, just retrieved a bit differently. I'm not really sure why <code>Deno.build.os</code> wasn't used. Maybe there's a good reason. 🤷</p>
<p>So that means that <code>process.platform</code>/<code>os.platform()</code> is the <strong>same value as <code>Deno.build.os</code> <em>except</em> it's <code>win32</code> instead of <code>windows</code></strong>. That's a string value of <code>darwin</code>, <code>linux</code>, <code>win32</code>, or any <a href="https://docs.rs/platforms/latest/platforms/target/enum.OS.html">other valid Rust target OS name</a>.</p>
<h3 id="codenodeprocesscode-codearchcode-amp-codenodeoscode-codearchcode"><code>node:process</code> <code>arch</code> &amp; <code>node:os</code> <code>arch()</code></h3>
<p>Deno's <code>node:os</code> <code>arch()</code> polyfill is just a wrapper around <code>node:process</code> <code>arch</code>.</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/ext/node/polyfills/os.ts#L115">denoland/deno: <code>ext/node/polyfills/os.ts</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">export</span> <span class="kd">function</span> <span class="nx">arch</span><span class="p">():</span> <span class="nx">string</span> <span class="p">{</span>
  <span class="k">return</span> <span class="nx">process</span><span class="p">.</span><span class="nx">arch</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Deno's <code>node:process</code> <code>arch</code> (or <code>process.arch</code>) is a variable...</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/ext/node/polyfills/process.ts#L80">denoland/deno: <code>ext/node/polyfills/process.ts</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">export</span> <span class="kd">let</span> <span class="nx">arch</span> <span class="o">=</span> <span class="dl">""</span><span class="p">;</span>
</code></pre></div></div>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/ext/node/polyfills/process.ts#L613">denoland/deno: <code>ext/node/polyfills/process.ts</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/** https://nodejs.org/api/process.html#process_process_arch */</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">defineProperty</span><span class="p">(</span><span class="nx">process</span><span class="p">,</span> <span class="dl">"</span><span class="s2">arch</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span>
  <span class="kd">get</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">arch</span><span class="p">;</span>
  <span class="p">},</span>
<span class="p">});</span>
</code></pre></div></div>
<p>...that's initialized at bootstrapping time to the result of an internal <code>arch()</code> getter.</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/ext/node/polyfills/process.ts#L1077">denoland/deno: <code>ext/node/polyfills/process.ts</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Should be called only once, in `runtime/js/99_main.js` when the runtime is</span>
<span class="c1">// bootstrapped.</span>
<span class="nx">internals</span><span class="p">.</span><span class="nx">__bootstrapNodeProcess</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span>
  <span class="nx">argv0Val</span><span class="p">:</span> <span class="nx">string</span> <span class="o">|</span> <span class="kc">undefined</span><span class="p">,</span>
  <span class="nx">args</span><span class="p">:</span> <span class="nx">string</span><span class="p">[],</span>
  <span class="nx">denoVersions</span><span class="p">:</span> <span class="nx">Record</span><span class="o">&lt;</span><span class="nx">string</span><span class="p">,</span> <span class="nx">string</span><span class="o">&gt;</span><span class="p">,</span>
  <span class="nx">nodeDebug</span><span class="p">:</span> <span class="nx">string</span><span class="p">,</span>
  <span class="nx">warmup</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span>
<span class="p">)</span> <span class="p">{</span>
    <span class="c1">// -- ✂️ SNIP --</span>
    <span class="nx">arch</span> <span class="o">=</span> <span class="nx">arch_</span><span class="p">();</span> <span class="c1">// 👈</span>
    <span class="nx">platform</span> <span class="o">=</span> <span class="nx">isWindows</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">win32</span><span class="dl">"</span> <span class="p">:</span> <span class="nx">Deno</span><span class="p">.</span><span class="nx">build</span><span class="p">.</span><span class="nx">os</span><span class="p">;</span>
    <span class="nx">pid</span> <span class="o">=</span> <span class="nx">Deno</span><span class="p">.</span><span class="nx">pid</span><span class="p">;</span>
    <span class="nx">ppid</span> <span class="o">=</span> <span class="nx">Deno</span><span class="p">.</span><span class="nx">ppid</span><span class="p">;</span>
    <span class="nx">initializeDebugEnv</span><span class="p">(</span><span class="nx">nodeDebug</span><span class="p">);</span>
    <span class="c1">// -- ✂️ SNIP --</span>
<span class="p">};</span>
</code></pre></div></div>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/ext/node/polyfills/process.ts#L46">denoland/deno: <code>ext/node/polyfills/process.ts</code></a></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">{</span>
  <span class="nx">arch</span> <span class="k">as</span> <span class="nx">arch_</span><span class="p">,</span> <span class="c1">// 👈</span>
  <span class="nx">chdir</span><span class="p">,</span>
  <span class="nx">cwd</span><span class="p">,</span>
  <span class="nx">env</span><span class="p">,</span>
  <span class="nx">nextTick</span> <span class="k">as</span> <span class="nx">_nextTick</span><span class="p">,</span>
  <span class="nx">version</span><span class="p">,</span>
  <span class="nx">versions</span><span class="p">,</span>
<span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">ext:deno_node/_process/process.ts</span><span class="dl">"</span><span class="p">;</span>
</code></pre></div></div>
<p>That <code>arch()</code> getter is a very well-defined and limited function that <strong>throws an error on all but three architectures</strong>.</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/ext/node/polyfills/_process/process.ts#L33">denoland/deno: <code>ext/node/polyfills/_process/process.ts</code></a></div>
<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/** Returns the operating system CPU architecture for which the Deno binary was compiled */</span>
<span class="k">export</span> <span class="kd">function</span> <span class="nx">arch</span><span class="p">():</span> <span class="kr">string</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">build</span><span class="p">.</span><span class="nx">arch</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">x86_64</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="dl">"</span><span class="s2">x64</span><span class="dl">"</span><span class="p">;</span>
  <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">build</span><span class="p">.</span><span class="nx">arch</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">aarch64</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="dl">"</span><span class="s2">arm64</span><span class="dl">"</span><span class="p">;</span>
  <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">build</span><span class="p">.</span><span class="nx">arch</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">riscv64gc</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="dl">"</span><span class="s2">riscv64</span><span class="dl">"</span><span class="p">;</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">"</span><span class="s2">unreachable</span><span class="dl">"</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Therefore, <strong>the exact guaranteed type for <code>node:process</code> <code>arch</code> or <code>node:os</code> <code>arch()</code> in Deno is <code>&quot;x64&quot; | &quot;arm64&quot; | &quot;riscv64&quot;</code></strong>. This is far more limited than Node.js' implementation of these APIs.</p>
<blockquote>
<p>Possible values are <code>'arm'</code>, <code>'arm64'</code>, <code>'ia32'</code>, <code>'loong64'</code>, <code>'mips'</code>, <code>'mipsel'</code>, <code>'ppc64'</code>, <code>'riscv64'</code>, <code>'s390x'</code>, and <code>'x64'</code>. The return value is equivalent to <code>process.arch</code>.</p>
</blockquote>
<p>— <a href="https://nodejs.org/api/os.html#osarch">Node.js <code>node:os</code> <code>arch()</code> docs</a></p>
<h3 id="codenodeoscode-codemachinecode"><code>node:os</code> <code>machine()</code></h3>
<p><code>machine()</code> is just <code>Deno.build.arch</code> with <code>aarch64</code> mapped to <code>arm64</code> instead.</p>
<div><a href="https://github.com/denoland/deno/blob/d17ae8ca9b0777c64934ae332b83ff0996a9fae0/ext/node/polyfills/os.ts#L258">denoland/deno: <code>ext/node/polyfills/os.ts</code></a></div>
<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/** Returns the machine type as a string */</span>
<span class="k">export</span> <span class="kd">function</span> <span class="nx">machine</span><span class="p">():</span> <span class="kr">string</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="nx">Deno</span><span class="p">.</span><span class="nx">build</span><span class="p">.</span><span class="nx">arch</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">aarch64</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="dl">"</span><span class="s2">arm64</span><span class="dl">"</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="nx">Deno</span><span class="p">.</span><span class="nx">build</span><span class="p">.</span><span class="nx">arch</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The full type is <em>probably</em> <code>&quot;arm64&quot; | &quot;x86_64&quot; | &quot;riscv64gc&quot;</code> but it could have more possible values.</p>]]></content><author><name>Jacob Hummer</name><email>jcbhmr@outlook.com</email></author><summary type="html"><![CDATA[I did some diving into what the possible values for these string enums are:]]></summary></entry><entry><title type="html">Apple crisp recipe</title><link href="https://jcbhmr.com/2025/10/31/apple-crisp/" rel="alternate" type="text/html" title="Apple crisp recipe" /><published>2025-10-31T00:00:00+00:00</published><updated>2025-10-31T00:00:00+00:00</updated><id>https://jcbhmr.com/2025/10/31/apple-crisp</id><content type="html" xml:base="https://jcbhmr.com/2025/10/31/apple-crisp/"><![CDATA[<p><em>TODO: Add images</em></p>
<h2 id="ingredients">Ingredients</h2>
<p>There's two parts: the main apple part and the topping powdery sprinkle part.</p>
<p><strong>The main apple part:</strong></p>
<p>Peel and cut up the apple into chunks. We use an apple corer &amp; spiral slicer with a hand crank. It works well.</p>
<ul>
<li><strong>4c</strong> sliced apples</li>
</ul>
<p><strong>The topping:</strong></p>
<ul>
<li><strong>1/3 cup</strong> brown sugar</li>
<li><strong>1/2 cup</strong> gluten-free flour</li>
<li><strong>1/2 cup</strong> oats</li>
<li><strong>1/3 cup</strong> shortening</li>
<li><strong>1 tsp</strong> cinnamon</li>
<li><strong>1 tsp</strong> nutmeg</li>
</ul>
<p>Pan: 8x8 inch. Use glass. <br />
Oven: 375°F (190°C) for 30 minutes. &quot;Golden brown&quot; on top.</p>
<h2 id="instructions">Instructions</h2>
<ol>
<li>Grease pan.</li>
<li>Place apples in pan. Use more or less apples to fill pan.</li>
<li>Use pastry cutter thing (biscuit masher) to mix topping ingredients into shortening crumbly bits.</li>
<li>Sprinkle topping on top.</li>
<li>Bake it.</li>
</ol>]]></content><author><name>Jacob Hummer</name><email>jcbhmr@outlook.com</email></author><summary type="html"><![CDATA[TODO: Add images]]></summary></entry><entry><title type="html">Bread recipe</title><link href="https://jcbhmr.com/2025/10/31/bread/" rel="alternate" type="text/html" title="Bread recipe" /><published>2025-10-31T00:00:00+00:00</published><updated>2025-10-31T00:00:00+00:00</updated><id>https://jcbhmr.com/2025/10/31/bread</id><content type="html" xml:base="https://jcbhmr.com/2025/10/31/bread/"><![CDATA[<p>Make this in a bread maker. 1.5 lb loaf. &quot;Regular&quot; settings on bread maker.</p>
<ul>
<li>1 1/4 cups water</li>
<li>2 Tbsp butter</li>
<li>3 1/3 cups bread flour</li>
<li>2 Tbsp dry milk</li>
<li>1 1/2 Tbsp sugar</li>
<li>1 1/4 tsp salt</li>
<li>2 tsp active dry yeast</li>
</ul>
<ol>
<li>Put the water in.</li>
<li>Add everything except the yeast. Make into a flat landmass so that there's no exposed water for the yeast to touch.</li>
<li>Make a depression for the yeast to sit.</li>
<li>Add the yeast into the depression.</li>
<li>Start the bread maker on &quot;regular&quot; settings.</li>
</ol>]]></content><author><name>Jacob Hummer</name><email>jcbhmr@outlook.com</email></author><summary type="html"><![CDATA[Make this in a bread maker. 1.5 lb loaf. &quot;Regular&quot; settings on bread maker.]]></summary></entry><entry><title type="html">Gluten-free peanut butter cookies</title><link href="https://jcbhmr.com/2025/10/31/gf-peanut-butter-cookies/" rel="alternate" type="text/html" title="Gluten-free peanut butter cookies" /><published>2025-10-31T00:00:00+00:00</published><updated>2025-10-31T00:00:00+00:00</updated><id>https://jcbhmr.com/2025/10/31/gf-peanut-butter-cookies</id><content type="html" xml:base="https://jcbhmr.com/2025/10/31/gf-peanut-butter-cookies/"><![CDATA[<p><em>TODO: Add images</em></p>
<ul>
<li>1 egg</li>
<li>1c sugar</li>
<li>1c peanut butter</li>
</ul>
<p>Oven: 350°F (175°C) for 12-15 minutes</p>
<ol>
<li>Mix everything in a mixer machine.</li>
<li>Bake it.</li>
</ol>]]></content><author><name>Jacob Hummer</name><email>jcbhmr@outlook.com</email></author><summary type="html"><![CDATA[TODO: Add images]]></summary></entry><entry><title type="html">Granola recipe</title><link href="https://jcbhmr.com/2025/10/31/granola/" rel="alternate" type="text/html" title="Granola recipe" /><published>2025-10-31T00:00:00+00:00</published><updated>2025-10-31T00:00:00+00:00</updated><id>https://jcbhmr.com/2025/10/31/granola</id><content type="html" xml:base="https://jcbhmr.com/2025/10/31/granola/"><![CDATA[<p><em>TODO: Add images</em></p>
<p>This recipe is in two parts: wet step and dry step.</p>
<p>Use a large 6 cup or more <strong>glass</strong> mixing bowl. Stuff is going in the microwave.</p>
<h2 id="wet-step">Wet step</h2>
<ul>
<li>2 Tbsp oil</li>
<li>1/2 cup honey</li>
<li>2/3 cup peanut butter</li>
</ul>
<ol>
<li>Use a liquid measure. Place oil in the cup first. Coat the sides.</li>
<li>Add honey using the graduations on the liquid measure. No extra measuring cup needed.</li>
<li>Pour into the big glass bowl.</li>
<li>Use a 2/3 cup dry measure for the peanut butter. Spatula recommended.</li>
<li>Microwave for 30 seconds.</li>
<li>Stir.</li>
</ol>
<h2 id="dry-step">Dry step</h2>
<ul>
<li>3 cups oats</li>
<li>1 cup flax meal</li>
<li>3/4 cup plus a bit coconut flakes</li>
</ul>
<p>Pan: 9x13 metal cake pan <br />
Oven: 350°F (175°C) for 11-14 minutes</p>
<ol>
<li>Add everything.</li>
<li>Mix. Use smooshing compacting motions to get sticky stuff everywhere.</li>
<li>Bake it.</li>
</ol>]]></content><author><name>Jacob Hummer</name><email>jcbhmr@outlook.com</email></author><summary type="html"><![CDATA[TODO: Add images]]></summary></entry><entry><title type="html">Guacamole recipe</title><link href="https://jcbhmr.com/2025/10/31/guacamole/" rel="alternate" type="text/html" title="Guacamole recipe" /><published>2025-10-31T00:00:00+00:00</published><updated>2025-10-31T00:00:00+00:00</updated><id>https://jcbhmr.com/2025/10/31/guacamole</id><content type="html" xml:base="https://jcbhmr.com/2025/10/31/guacamole/"><![CDATA[<p>This is very vague. Use whatever amount looks good.</p>
<ul>
<li>Avocados</li>
<li>Tomato bits</li>
<li>A bit of raw onion bits</li>
<li>Lime juice</li>
<li>Garlic or garlic powder</li>
<li>Salt &amp; pepper</li>
<li>Any other seasonings you like i.e. spicy powder or hot sauce</li>
</ul>
<p>For 4 people use about 2 avocados and 2 roma tomatoes.</p>]]></content><author><name>Jacob Hummer</name><email>jcbhmr@outlook.com</email></author><summary type="html"><![CDATA[This is very vague. Use whatever amount looks good.]]></summary></entry><entry><title type="html">Peanut butter cookies recipe</title><link href="https://jcbhmr.com/2025/10/31/peanut-butter-cookies/" rel="alternate" type="text/html" title="Peanut butter cookies recipe" /><published>2025-10-31T00:00:00+00:00</published><updated>2025-10-31T00:00:00+00:00</updated><id>https://jcbhmr.com/2025/10/31/peanut-butter-cookies</id><content type="html" xml:base="https://jcbhmr.com/2025/10/31/peanut-butter-cookies/"><![CDATA[<p><em>TODO: Add images</em></p>
<ul>
<li><strong>1/2 cup</strong> sugar</li>
<li><strong>1/2 cup</strong> brown sugar</li>
<li><strong>1/2 cup</strong> peanut butter</li>
<li><strong>1/4 cup</strong> shortening</li>
<li><strong>1/4 cup</strong> butter (softened)</li>
<li><strong>1</strong> egg</li>
<li><strong>1 1/4 cups</strong> all-purpose flour</li>
<li><strong>3/4 tsp</strong> baking soda</li>
<li><strong>1/2 tsp</strong> baking powder</li>
</ul>
<p>Oven: 350°F (175°C) for 10-12 minutes</p>
<ol>
<li>Mix everything. Use a mixer machine.</li>
<li>Bake it.</li>
<li>Let cookies cook on the pan after coming out of the oven.</li>
</ol>
<p>I like these cookies.</p>]]></content><author><name>Jacob Hummer</name><email>jcbhmr@outlook.com</email></author><summary type="html"><![CDATA[TODO: Add images]]></summary></entry><entry><title type="html">GitHub Pages redirect to new domain</title><link href="https://jcbhmr.com/2025/03/13/gh-pages-domain-redirect/" rel="alternate" type="text/html" title="GitHub Pages redirect to new domain" /><published>2025-03-13T00:00:00+00:00</published><updated>2025-03-13T00:00:00+00:00</updated><id>https://jcbhmr.com/2025/03/13/gh-pages-domain-redirect</id><content type="html" xml:base="https://jcbhmr.com/2025/03/13/gh-pages-domain-redirect/"><![CDATA[<p>Here's the code:</p>
<div><code>404.html</code></div>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;!DOCTYPE html&gt;</span>
<span class="nt">&lt;html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;head&gt;</span>
    <span class="nt">&lt;meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"viewport"</span> <span class="na">content=</span><span class="s">"width=device-width, initial-scale=1.0"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;meta</span> <span class="na">http-equiv=</span><span class="s">"refresh"</span> <span class="na">content=</span><span class="s">"0; url=DEST_ROOT_URL"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"robots"</span> <span class="na">content=</span><span class="s">"noindex"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;title&gt;</span>Moved to DEST_ROOT_URL<span class="nt">&lt;/title&gt;</span>
    <span class="nt">&lt;script&gt;</span>
      <span class="nx">location</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="dl">"</span><span class="s2">DEST_ROOT_URL</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">location</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">slice</span><span class="p">(</span><span class="nx">origin</span><span class="p">.</span><span class="nx">length</span><span class="p">));</span>
    <span class="nt">&lt;/script&gt;</span>
  <span class="nt">&lt;/head&gt;</span>
  <span class="nt">&lt;body&gt;</span>
    <span class="nt">&lt;p&gt;</span>
      Moved to <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"DEST_ROOT_URL"</span><span class="nt">&gt;</span>DEST_ROOT_URL<span class="nt">&lt;/a&gt;</span>
    <span class="nt">&lt;/p&gt;</span>
  <span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span>
</code></pre></div></div>
<p>Where <code>DEST_ROOT_URL</code> is the destination URL root <strong>without the trailing slash</strong> since <code>origin</code> doesn't include the trailing slash.</p>
<p>The trick is the JavaScript in the <code>404.html</code> page which is rendered when a URL is not found anywhere in your GitHub Pages site. The <code>&lt;script&gt;</code> tag is in <code>&lt;head&gt;</code> so it <em>should</em> run before the page is even shown. It <strong>replaces</strong> (no back-button history entry) the current URL with the one you give it. In this case that's the current URL (<code>location.toString()</code>) minus the <code>https://example.com</code> prefix (<code>.slice(origin.length)</code>) with the destination URL prepended to it.</p>
<p>For example:</p>
<ol>
<li>Navigate to <code>https://example.org/hello-world</code></li>
<li>404, serve <code>404.html</code></li>
<li><code>&quot;https://example.org/hello-world&quot;.slice(&quot;https://example.org&quot;.length)</code></li>
<li><code>location.replace(&quot;https://example.com&quot; + $3)</code></li>
</ol>]]></content><author><name>Jacob Hummer</name><email>jcbhmr@outlook.com</email></author><summary type="html"><![CDATA[Here's the code:]]></summary></entry></feed>