<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Bryan Hughes</title>
    <description>The latest articles on Forem by Bryan Hughes (@nebrius).</description>
    <link>https://forem.com/nebrius</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F140243%2F0da9aa6d-7fc2-4bbe-ac9a-0f27b4a18170.jpeg</url>
      <title>Forem: Bryan Hughes</title>
      <link>https://forem.com/nebrius</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nebrius"/>
    <language>en</language>
    <item>
      <title>Introducing React Strapped: a Bootstrap Data Management Library</title>
      <dc:creator>Bryan Hughes</dc:creator>
      <pubDate>Mon, 06 Nov 2023 19:38:33 +0000</pubDate>
      <link>https://forem.com/nebrius/introducing-react-strapped-a-bootstrap-data-management-library-5agp</link>
      <guid>https://forem.com/nebrius/introducing-react-strapped-a-bootstrap-data-management-library-5agp</guid>
      <description>&lt;p&gt;I've been using Next.js in production since version 10, and I'm a big fan overall. Like everything in life though, Next.js isn't perfect. One of my biggest pain points isn't actually due to Next.js itself, but rather a misalignment between Next.js and modern state management tools: managing page-specific bootstrap data.&lt;/p&gt;

&lt;p&gt;So I create an open source library to fix it: &lt;a href="https://github.com/nebrius/react-strapped"&gt;React Strapped&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;Single-Page Applications (SPAs) have been the predominant method of writing applications for some time in the web world, and for good reason. SPAs brought us high performance when navigating around the sight, as well as the ability for more complex state and context across routes. SPAs have their own downsides though, and is why we're starting to migrate away from them.&lt;/p&gt;

&lt;p&gt;Next.js is a SPA-like system in the sense that Next.js provides client-side routing, instead of doing full page loads when navigating between routes. However, Next.js isn't really a SPA system because each route has its own code bundles, bootstrap data, etc. that are by default independent between pages. This allows each route to only need to load the data and code that route needs, increasing performance. Due to this hybrid nature, I've personally started calling Next.js' a "client-side MPA" framework, or csMPA.&lt;/p&gt;

&lt;p&gt;I really appreciate Next.js' csMPA implementation because it greatly simplifies implementing and maintaining applications with multiple and varied routes compared with previous SPA architectures.&lt;/p&gt;

&lt;p&gt;There's one area though that I've historically struggled with while using Next.js: how to access bootstrap data in a reliable and scalable manner. To be clear, accessing bootstrap data is outside of Next.js' jurisdiction and is instead the responsibility of state management libraries. Unfortunately I haven't found any state management libraries that handle bootstrap data from Next.js cleanly.&lt;/p&gt;

&lt;p&gt;So I implemented my own library specifically to solve this use case: &lt;a href="https://github.com/nebrius/react-strapped"&gt;React Strapped&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem statement &lt;sup&gt;[1]&lt;/sup&gt;
&lt;/h2&gt;

&lt;p&gt;Before I dive into how React Strapped works, let's spend some time really defining the problem, because it wasn't immediately obvious to me.&lt;/p&gt;

&lt;p&gt;React has a number of popular state management libraries, such as &lt;a href="https://react-redux.js.org/"&gt;Redux&lt;/a&gt;, &lt;a href="https://github.com/pmndrs/zustand"&gt;Zustand&lt;/a&gt;, &lt;a href="https://jotai.org/"&gt;Jotai&lt;/a&gt;, and &lt;a href="https://recoiljs.org/"&gt;Recoil&lt;/a&gt;. While each of these state management libraries brings their own opinions to state management, none of them have opinions on how to load bootstrap data from Next.js. Specifically, bootstrap data in Next.js a) varies from page to page and b) is not available to state management libraries until first render. As we'll see, this creates friction.&lt;/p&gt;

&lt;p&gt;Bootstrap data in csMPAs typically have the following characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some data is always available on all routes.

&lt;ul&gt;
&lt;li&gt;Examples include: data about the current user, feature/experimentation flags, etc.&lt;/li&gt;
&lt;li&gt;This data is always available, and can be consumed "no questions asked."&lt;/li&gt;
&lt;li&gt;In Next.js, this data is typically populated via a centralized helper function that is called from &lt;a href="https://nextjs.org/docs/pages/api-reference/functions/get-server-side-props"&gt;&lt;code&gt;getServerSideProps&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Other data is only available on certain routes.

&lt;ul&gt;
&lt;li&gt;Examples include settings information that's only available on a settings page, but not on the home page.&lt;/li&gt;
&lt;li&gt;This data is &lt;em&gt;not&lt;/em&gt; available on all pages, and so care must be take to only access this data on the settings page.&lt;/li&gt;
&lt;li&gt;In Next.js, this data is typically populated via one-off code in a specific route(s)' &lt;a href="https://nextjs.org/docs/pages/api-reference/functions/get-server-side-props"&gt;&lt;code&gt;getServerSideProps&lt;/code&gt;&lt;/a&gt; implementation.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Bootstrap data is not available until the first render of the application.

&lt;ul&gt;
&lt;li&gt;In Next.js, bootstrap data generated in &lt;a href="https://nextjs.org/docs/pages/api-reference/functions/get-server-side-props"&gt;&lt;code&gt;getServerSideProps&lt;/code&gt;&lt;/a&gt; is passed as component properties to the top level component.&lt;/li&gt;
&lt;li&gt;The implication of this pattern is that any state management declared at module scope, such as &lt;code&gt;atom()&lt;/code&gt; constructors in Jotai and Recoil, do not have access to this data at time of construction.&lt;/li&gt;
&lt;li&gt;This limitation means we can't use these libraries preferrerd state initialization techniques.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Data during SSR needs to be scoped to a React context and not be available globally.

&lt;ul&gt;
&lt;li&gt;A Next.js server is rendering multiple requests from multiple users more or less at once, meaning global data is not a pragmatic option since it wouldn't be "scoped" to a specific request.&lt;/li&gt;
&lt;li&gt;While it's possible to use global data safely in Next.js applications, it's &lt;em&gt;very&lt;/em&gt; tricky to completely prevent all data "leaks" at all times. As such, I think it's best to avoid this pattern as whole.&lt;/li&gt;
&lt;li&gt;This means we can't do tricks for Jotai/Recoil like creating a global promise we attach to each atom's initializer, and then resolving it once we get the bootstrap data.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Taking these characteristics into account when considering state management libraries, we end up with these requirements for state management:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Initialize the store/atoms/etc. synchronously during the first render&lt;/li&gt;
&lt;li&gt;Allow global data to be used anywhere, but prevent page specific data from being used outside of that page&lt;/li&gt;
&lt;li&gt;Only load state management code on a page if they are used on that page&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Redux/Zustand handle requirement 1 well. Jotai/Recoil handle requirements 1 and 3 well, but only if we're not trying to solve requirement 2 (see below for an explanation). None of these four handle requirement 2 well.&lt;/p&gt;

&lt;p&gt;React Strapped exists to handle all 3 requirements well. That said, React Strapped is &lt;em&gt;not&lt;/em&gt; a replacement for the four state management libraries mentioned, and is indeed intended to be used in conjunction with them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wait, why doesn't Jotai/Recoil handle requirement 2? &lt;sup&gt;[2]&lt;/sup&gt;
&lt;/h3&gt;

&lt;p&gt;It may not be immediately obvious why Jotai/Recoil don't handle all requirements well. It &lt;em&gt;certainly&lt;/em&gt; wasn't obvious to me at first, and my frustrations getting them to work specifically is what led me to create React Strapped. But why is that? It turns out that initializing Recoil with runtime bootstrap data &lt;a href="https://github.com/facebookexperimental/Recoil/issues/750"&gt;is tricky and non-obvious&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Specific challenges include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In multi-page apps, Jotai/Recoil must be initialized with bootstrap data that's been prop-drilled to a component

&lt;ul&gt;
&lt;li&gt;Thus, bootstrap data is not available to use with the default value mechanisms Jotai/Recoil provide, preventing us from using the standard way of initializing atoms.&lt;/li&gt;
&lt;li&gt;The recommended way to solve this challenge in Recoil is to initialize atoms with the &lt;code&gt;initializeState&lt;/code&gt; property in &lt;code&gt;RecoilRoot&lt;/code&gt;. As we'll see in challenge 2, this is not viable in multi-page apps.&lt;/li&gt;
&lt;li&gt;Similarly, Jotai provides the &lt;code&gt;useHydrateAtoms&lt;/code&gt; hook, but also isn't viable for the same reasons&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Bootstrap data varies from page to page

&lt;ul&gt;
&lt;li&gt;Thus, we need to initialize &lt;em&gt;different atoms&lt;/em&gt; depending on which route we're on.&lt;/li&gt;
&lt;li&gt;While it's possible, if unwieldy, to use a &lt;code&gt;switch(currentRoute)&lt;/code&gt; statement to &lt;em&gt;initialize&lt;/em&gt; only the atoms needed per route, we have to statically import &lt;em&gt;every&lt;/em&gt; atom from &lt;em&gt;every&lt;/em&gt; page to do the initialization. In other words, we're including code in our bundles that's never used.&lt;/li&gt;
&lt;li&gt;Dynamic imports are typically how we include dependencies conditionally, but their asynchronous nature is incompatible with the synchronous &lt;code&gt;initializeState&lt;/code&gt; prop/&lt;code&gt;useHydrateAtoms&lt;/code&gt; hook, which is otherwise the only way to conditionally import atoms based on the current route.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;State needs to be scoped to a React context and not used globally

&lt;ul&gt;
&lt;li&gt;A Next.js server is rendering multiple requests from multiple users more or less at once, meaning global data is not an option since it wouldn't be "scoped" to a specific request.&lt;/li&gt;
&lt;li&gt;This means we can't do tricks like creating a global promise we attach to each atoms &lt;code&gt;default&lt;/code&gt; prop, and then resolving it once we get the bootstrap data.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of these challenges together mean that Jotai/Recoil do not currently include any mechanisms for conveniently initializing themselves with bootstrapped data in csMPAs.&lt;/p&gt;

&lt;h2&gt;
  
  
  How React Strapped works &lt;sup&gt;[3]&lt;/sup&gt;
&lt;/h2&gt;

&lt;p&gt;React Strapped works by creating a React context to hold bootstrap data, and special hooks for accessing this data. We call an instance of provider+hooks associated with a piece of bootstrap data a "strap." Unlike other state management libraries, these providers+hooks are intentionally designed so that more than one provider can be used at a time without impacting other providers. We'll see what this means and why it's important in the next section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple example
&lt;/h3&gt;

&lt;p&gt;This example shows a minimal example using React Strapped. It's written in TypeScript to a) demonstrate how TypeScript types flows through the library and b) to give a sense of what data is expected where. You can absolutely use this library without using TypeScript though.&lt;/p&gt;

&lt;p&gt;First, let's create our provider and hooks in a file called &lt;code&gt;state.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createStrappedProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-strapped&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;MyBootstrapData&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// First, we create the strap, which includes the context&lt;/span&gt;
&lt;span class="c1"&gt;// provider and some helper functions for creating hooks.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myStrap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createStrap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyBootstrapData&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Next, export the provider, which is used to make data &lt;/span&gt;
&lt;span class="c1"&gt;// available to components.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyStrapProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myStrap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Finally create a hook for accessing the current user &lt;/span&gt;
&lt;span class="c1"&gt;// included in the bootstrap data. The callback is called &lt;/span&gt;
&lt;span class="c1"&gt;// once on first render to initialize the strap value &lt;/span&gt;
&lt;span class="c1"&gt;// returned by the hook.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useCurrentUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myStrap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createUseStrappedValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;currentUser&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's create some UI in a Next.js page component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyBootstrapData&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./state&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyStrapProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useCurrentUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./state&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PageProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;bootstrapData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyBootstrapData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// If you're not familiar with Next.js, this function runs&lt;/span&gt;
&lt;span class="c1"&gt;// on a server and is responsible for fetching bootstrap &lt;/span&gt;
&lt;span class="c1"&gt;// data. The value of the `props` property is passed as &lt;/span&gt;
&lt;span class="c1"&gt;// props to the default export React component in this file.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getServerSideProps&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PageProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;bootstrapData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Philip J Fry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;_026&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// This default export is the root component in a Next.js &lt;/span&gt;
&lt;span class="c1"&gt;// page. The props passed to this component come from the &lt;/span&gt;
&lt;span class="c1"&gt;// server via `getServerSideProps`.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;bootstrapData&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;PageProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// We include our strap provider and give it the &lt;/span&gt;
    &lt;span class="c1"&gt;// bootstrap data.  This initializes data and make it &lt;/span&gt;
    &lt;span class="c1"&gt;// immediately available for  use via strap hooks, e.g. &lt;/span&gt;
    &lt;span class="c1"&gt;// `useCurrentUser`.&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyStrapProvider&lt;/span&gt; &lt;span class="na"&gt;bootstrapData&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;bootstrapData&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MyStrapProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// We use the hook created above, which makes sure that &lt;/span&gt;
  &lt;span class="c1"&gt;// we're calling this hook in a component with &lt;/span&gt;
  &lt;span class="c1"&gt;// &amp;lt;MyStrapProvider&amp;gt; as a  parent in the component tree.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useCurrentUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// Prints "Hello Philip J Fry"&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Multi-page Apps
&lt;/h3&gt;

&lt;p&gt;React Strapped is designed specifically for csMPAs, which React Strapped supports via multiple Provider components. You can have as many providers as you want with any amount of nesting. All hooks associated with providers are available for use, regardless of where that provider sits in relation to other providers.&lt;/p&gt;

&lt;p&gt;This nesting works differently than in Recoil and Jotai. In Jotai, you can only use atom values associated with the closest &lt;a href="https://github.com/pmndrs/jotai/discussions/682"&gt;&lt;code&gt;Provider&lt;/code&gt;&lt;/a&gt;. In Recoil, you can either only access the root-most &lt;a href="https://recoiljs.org/docs/api-reference/core/RecoilRoot/"&gt;&lt;code&gt;RecoilRoot&lt;/code&gt;&lt;/a&gt;, or the closest &lt;code&gt;RecoilRoot&lt;/code&gt; if the &lt;code&gt;override&lt;/code&gt; property is specified for that root. Neither of these allow you to access all values from all providers, regardless of nesting.&lt;/p&gt;

&lt;p&gt;Why does this distinction matter? In multi-page applications, we often have a set of bootstrap data that is common to all pages as well as bootstrap data that is specific to a page. The natural setup to handle these two sets of data is to create one provider for the common bootstrap data that exists on all pages, and then per-page providers that contain just those pages' data. React Strapped supports exactly this provider setup by allowing any number of straps to be nested, and propagating data appropriately between them.&lt;/p&gt;

&lt;p&gt;In code, we set this up like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;commonBootstrapData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;myPageBootstrapData&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// Add the common provider, which is used on all pages&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyCommonStrapProvider&lt;/span&gt;
      &lt;span class="na"&gt;bootstrapData&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;commonBootstrapData&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* SomeCommonComponents only has access to hooks from 
          MyCommonStrapProvider */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SomeCommonComponents&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Add the page specific provider here, which is only 
          used on this page */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyPageSpecificStrapProvider&lt;/span&gt;
        &lt;span class="na"&gt;bootstrapData&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;myPageBootstrapData&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* SomePageSpecificComponents has access to all 
            hooks from both MyCommonStrapProvider _and_ 
            MyPageSpecificStrapProvider */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SomePageSpecificComponents&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MyPageSpecificStrapProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MyCommonStrapProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this setup, the &lt;code&gt;SomePageSpecificComponents&lt;/code&gt; component tree has access to all hooks associated with both the common and page specific straps, but the &lt;code&gt;SomeCommonComponents&lt;/code&gt; component tree &lt;em&gt;only&lt;/em&gt; has access to hooks associated with the common strap.&lt;/p&gt;

&lt;p&gt;If bootstrap data exists across two or more pages, but not all pages, you can create a third strap that is shared between these pages that sits between the common strap and the page specific strap.&lt;/p&gt;

&lt;p&gt;To ensure that &lt;code&gt;SomeCommonComponents&lt;/code&gt; code cannot access the page specific hooks, these hooks provide guardrails against accessing data from the wrong place. If you try and call a hook based on &lt;code&gt;MyPageSpecificStrapProvider&lt;/code&gt; from &lt;code&gt;SomeCommonComponents&lt;/code&gt;, then you'll get an error saying you're trying to access it from the wrong place, like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eO1mLGnO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/nebrius/react-strapped/main/img/access-error.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eO1mLGnO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/nebrius/react-strapped/main/img/access-error.png" alt="Image showing a hook access error" width="800" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;And that's that. The library is very simple at only 138 lines of code with zero dependencies. I'm really excited about this approach because it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is technically and conceptually very simple&lt;/li&gt;
&lt;li&gt;Removes a lot of boilerplate otherwise required to create safe access to bootstrap data&lt;/li&gt;
&lt;li&gt;Provides strong guardrails for how we access page-specific bootstrap data in a csMPA&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'd love to hear what you think about this library!&lt;/p&gt;

&lt;h2&gt;
  
  
  Footnotes
&lt;/h2&gt;

&lt;p&gt;[1] Most of this content comes from the &lt;a href="https://github.com/nebrius/react-strapped#motivation"&gt;Motivation section of the React Strapped README.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[2] Most of this content comes from the &lt;a href="https://github.com/nebrius/recoil-bootstrap#motivation"&gt;Motivation section of the Recoil Bootstrap README&lt;/a&gt;, an early version of what eventually became Recoil Strapped.&lt;/p&gt;

&lt;p&gt;[3] Most of this content comes from the &lt;a href="https://github.com/nebrius/recoil-bootstrap#getting-started"&gt;Getting Started section of the React Strapped README&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>state</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Interacting with Microsoft's LED art piece at JSConf EU</title>
      <dc:creator>Bryan Hughes</dc:creator>
      <pubDate>Thu, 30 May 2019 12:41:15 +0000</pubDate>
      <link>https://forem.com/azure/interacting-with-microsoft-s-led-art-piece-at-jsconf-eu-2cph</link>
      <guid>https://forem.com/azure/interacting-with-microsoft-s-led-art-piece-at-jsconf-eu-2cph</guid>
      <description>&lt;p&gt;Hi CSSConf/JSConf EU friend! If you're here, then you've probably heard that we brought an LED art piece with us to the conferences. This article will tell you all about this project at a high level, and how you can engage with it.&lt;/p&gt;

&lt;p&gt;This art piece is very loosely inspired by bamboo forests. This device features multiple LED "shoots" that are controlled from the cloud, by you. The hardware was built by my amazing teammate and Microsoft Cloud Advocate PM for Europe &lt;a href="https://dev.to/jansche"&gt;Jan Schenk&lt;/a&gt; from designs I created. Here is what the finished version of the art piece looks like:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Y4pN53zziyA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Creating animations for this piece may look daunting at first glance, but don't worry. I put a lot of work into this project over the years to make it approachable for a wide variety of folks.&lt;/p&gt;

&lt;p&gt;This project is based on another project I created called &lt;a href="https://github.com/nebrius/raver-lights/"&gt;Raver Lights&lt;/a&gt;. I started this project back in 2016 to control LEDs on art pieces destined for Burning Man and similar events. Suffice to say, it's pretty well tested at this point, having survived the extremes of the desert multiple times now.&lt;/p&gt;

&lt;p&gt;There are two ways to control the animations in this piece. The first way is at our booth using a web interface running on the new &lt;a href="https://www.microsoftedgeinsider.com/"&gt;Chromium-based version of Edge&lt;/a&gt; (ask us about it!). The second is by creating your own &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/?WT.mc_id=devto-blog-brhugh"&gt;Azure Function-based Serverless endpoint&lt;/a&gt;, which gives you a lot more control over the animation than the booth interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Animations
&lt;/h2&gt;

&lt;p&gt;Don't let the name fool you, there's nothing boring about these animations! I'm just bad at naming things, to be completely honest.&lt;/p&gt;

&lt;p&gt;At the booth, you can submit an animation from tablets we'll have on hand running the new &lt;a href="https://www.microsoftedgeinsider.com/"&gt;Chromium-based version of Edge&lt;/a&gt;. If you haven't heard yet, we're &lt;a href="https://github.com/MicrosoftEdge/MSEdge"&gt;rewriting our browser to be based on Chromium&lt;/a&gt;! We're still hard at work getting it ready for general use, but you can download canary and dev channel builds today for Windows 10 &lt;em&gt;and&lt;/em&gt; macOS.&lt;/p&gt;

&lt;p&gt;I decided to have a little fun building this app. My design skills may not be the best, but I did get to use some pretty new technologies here: CSS Grid, the new CSS filter property, and Web Assembly. If I'm at the booth, ask me all about how I wrote it (I'm the one with purple hair). You can also check out the &lt;a href="https://github.com/nebrius/azure-led-booth/tree/master/clients"&gt;code on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While these animations are certainly pretty, you don't quite get the same control as custom animations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom
&lt;/h2&gt;

&lt;p&gt;You can also write a custom Azure Function to gain complete control of the animation. For the curious, here is the code to create the default animation you see running at the booth:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;createWaveParameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;createMovingWave&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;createSolidColorWave&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;createPulsingWave&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rvl-node-animations&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createWaveParameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="c1"&gt;// Create the moving purple wave on top&lt;/span&gt;
  &lt;span class="nx"&gt;createMovingWave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;215&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="c1"&gt;// Creating a pulsing green on top of the blue, but below the purple&lt;/span&gt;
  &lt;span class="nx"&gt;createPulsingWave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="c1"&gt;// Create the solid blue on bottom&lt;/span&gt;
  &lt;span class="nx"&gt;createSolidColorWave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;170&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code uses the same tools you'll use to create a custom animation. Not so bad, right? Trust me, writing the animation engine that takes these parameters was &lt;em&gt;considerably&lt;/em&gt; more difficult.&lt;/p&gt;

&lt;p&gt;To get started writing a custom animation, head over to our &lt;a href="https://github.com/bnb/jsconf-eu-led"&gt;starter repo&lt;/a&gt; and read the instructions there.&lt;/p&gt;

&lt;p&gt;Happy Hacking!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>azure</category>
      <category>serverless</category>
      <category>iot</category>
    </item>
    <item>
      <title>A New Coding Style for Switch Statements in JavaScript/TypeScript</title>
      <dc:creator>Bryan Hughes</dc:creator>
      <pubDate>Thu, 16 May 2019 16:08:42 +0000</pubDate>
      <link>https://forem.com/nebrius/a-new-coding-style-for-switch-statements-in-javascript-typescript-ipe</link>
      <guid>https://forem.com/nebrius/a-new-coding-style-for-switch-statements-in-javascript-typescript-ipe</guid>
      <description>&lt;p&gt;I've recently adopted a new coding style for &lt;code&gt;switch&lt;/code&gt; statements in JavaScript (well, technically TypeScript), and I'm really curious to hear what you all think about it!&lt;/p&gt;

&lt;p&gt;Before I discuss the style, let me explain the problem I'm trying to solve. It's not uncommon for switch statements to have somewhat-repeated code between cases, but with variations in each case such that you can't easily abstract it. Let's take this example, written in ES5 (I promise there's a reason why).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isBasic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getBasicEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Processing basic entry "&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;doBasicProcessing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isCustom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getCustomEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Processing custom entry "&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;doCustomprocessing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unknown flag &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;myFlag&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cool, it's a basic switch statement and it works fine. Now, let's convert this to ES2015+.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isBasic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getBasicEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Processing basic entry "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;doBasicProcessing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isCustom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getCustomEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Processing custom entry "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;doCustomprocessing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unknown flag &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;myFlag&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uh-oh, we now get a &lt;code&gt;SyntaxError&lt;/code&gt; exception when we run this code! The problem here is that &lt;code&gt;const&lt;/code&gt; variable name &lt;code&gt;entry&lt;/code&gt; cannot be declared twice in the same scope. Because of how scoping rules work, the entire &lt;code&gt;switch&lt;/code&gt; statement is one single scope.&lt;/p&gt;

&lt;p&gt;We could solve this by naming each &lt;code&gt;entry&lt;/code&gt; with a different variable name, but honestly I find that kind of annoying. We could also create a helper function for each case, but that feels excessive to me for such short case statements.&lt;/p&gt;

&lt;p&gt;So here's what I figured out, and I've started using it in all my code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isBasic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getBasicEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Processing basic entry "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;doBasicProcessing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isCustom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getCustomEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Processing custom entry "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;doCustomprocessing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unknown flag &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;myFlag&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I wrap each case statement in &lt;code&gt;{}&lt;/code&gt;, which creates a new scope on a per-case basis. This solves the problem, and I think is kind of elegant myself. It's not very common though.&lt;/p&gt;

&lt;p&gt;What do you all think? Does this seem like a good approach? Do you have a different approach that you use? I'd love to hear it in the comments!&lt;/p&gt;

&lt;h2&gt;
  
  
  Update:
&lt;/h2&gt;

&lt;p&gt;Thank you all for the discussion so far, it's been great! I ended up creating a new module called &lt;a href="https://www.npmjs.com/package/conditional-reduce"&gt;conditional-reduce&lt;/a&gt; that automates another approach I hadn't thought of before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;reduce&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;conditional-reduce&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Dogs are great pets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cat&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;s are also great&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt; &lt;span class="c1"&gt;// Prints "Dogs are great pets"&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bird&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Dogs are great pets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cat&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;s are also great&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt; &lt;span class="c1"&gt;// Throws 'Invalid conditional value "bird"' exception&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;curry&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;conditional-reduce&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dogReducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;curry&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Dogs are great pets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cat&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;s are also great&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dogReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Prints "Dogs are great pets"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dogReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bird&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Throws 'Invalid conditional value "bird"' exception&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thank you &lt;a class="mentioned-user" href="https://dev.to/avalander"&gt;@avalander&lt;/a&gt; and &lt;a class="mentioned-user" href="https://dev.to/john_papa"&gt;@john_papa&lt;/a&gt; for the discussion that prompted this!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>discuss</category>
      <category>coding</category>
    </item>
    <item>
      <title>Building an Interactive LED Art Piece for JSConf EU</title>
      <dc:creator>Bryan Hughes</dc:creator>
      <pubDate>Fri, 10 May 2019 18:02:30 +0000</pubDate>
      <link>https://forem.com/azure/building-an-interactive-led-art-piece-for-jsconf-eu-3gdj</link>
      <guid>https://forem.com/azure/building-an-interactive-led-art-piece-for-jsconf-eu-3gdj</guid>
      <description>&lt;p&gt;JSConf EU is arguably the most important JavaScript conference of the year. Many important technologies have been announced at JSConf EU, such as Node.js, and a wide array of developers come from all over the globe to attend. Microsoft is sponsoring the conference this year, and we're bringing something fun along: an LED powered art piece that you can control from the booth and with your own custom Serverless implementation!&lt;/p&gt;

&lt;p&gt;This series of blog posts will dive into how we built this project.&lt;/p&gt;

&lt;p&gt;I've been involved in LED art for a while now after I was inspired by my experiences with Burning Man and related events. I've been developing a &lt;a href="https://github.com/nebrius/raver-lights/" rel="noopener noreferrer"&gt;wireless lighting control system&lt;/a&gt; for programmable LED art for a few years now, and it's pretty rock-solid at this point. This is the perfect system to base our booth code on. I took on the lead role for the project since I created the base infrastructure for it, and I'm fortunate to work with my amazing teammates &lt;a href="https://dev.to/jansche"&gt;Jan Schenk&lt;/a&gt;, &lt;a href="https://dev.to/shehackspurple"&gt;Tanya Janca&lt;/a&gt;, &lt;a href="https://dev.to/bnb"&gt;Tierney Cyren&lt;/a&gt;, and &lt;a href="https://dev.to/noopkat"&gt;Suz Hinton&lt;/a&gt; to bring it to life. If you're curious what this system looks like, here's a tech demo:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/nYG6840g4mw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;For JSConf EU, I designed an art piece loosely inspired by bamboo forests. This device will feature multiple LED "shoots" that are controlled from the cloud.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F333veu5w6ie9yjgmf1bh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F333veu5w6ie9yjgmf1bh.png" alt="LED piece CAD rendering"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This piece uses custom hardware I originally designed for Burning Man based on the &lt;a href="https://en.wikipedia.org/wiki/ESP8266" rel="noopener noreferrer"&gt;ESP8266 12-S WiFi enabled microcontroller&lt;/a&gt;. These little boards control the lights themselves and connect to a Raspberry Pi over WiFi. The Raspberry Pi will connect to Azure using &lt;a href="https://docs.microsoft.com/en-us/azure/iot-edge/?WT.mc_id=devto-blog-brhugh" rel="noopener noreferrer"&gt;Azure IoT Hub&lt;/a&gt;, and from there we can hook into all sorts of cloud goodness!&lt;/p&gt;

&lt;p&gt;The system is comprised of three sets of code: browser UI code, server code in the form of &lt;a href="https://azure.microsoft.com/en-us/services/functions/?WT.mc_id=devto-blog-brhugh" rel="noopener noreferrer"&gt;Azure Functions&lt;/a&gt;, and controller code running on the Raspberry Pi. Here is the complete architecture diagram (minus the ESP8266s  ):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fduro6k76csfhbvdbulkx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fduro6k76csfhbvdbulkx.png" alt="Architecture Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Browser UI code consists of two clients. The first client will be running on tablets at the booth, and will be running the new &lt;a href="https://www.microsoftedgeinsider.com/en-us/" rel="noopener noreferrer"&gt;Chromium-based version of Edge&lt;/a&gt;. This client will allow people to walk up to the booth and give them basic control over the animations. This interface will be intentionally limited though. For more advanced animations, we'll have another web UI that will allow people to submit custom animations, implementing using their own &lt;a href="https://azure.microsoft.com/en-us/services/functions/?WT.mc_id=devto-blog-brhugh" rel="noopener noreferrer"&gt;Azure Function&lt;/a&gt;, where they have full control over the animations.&lt;/p&gt;

&lt;p&gt;The server code consists of four Azure Functions. One Azure Function will implement the endpoint for submitting basic animations, and another will implement the endpoint for submitting custom animations. Another Azure Function will be used to return the current queue of animations, so folks can see when their animation will run. The final Azure Function will run on a timer, and pulls the next animation off of the queue and sends it to the Raspberry Pi for display using &lt;a href="https://docs.microsoft.com/en-us/azure/iot-edge/?WT.mc_id=devto-blog-brhugh" rel="noopener noreferrer"&gt;Azure IoT Hub&lt;/a&gt;. The animation queue is implemented using &lt;a href="https://docs.microsoft.com/en-us/azure/storage/queues/storage-nodejs-how-to-use-queues?WT.mc_id=devto-blog-brhugh" rel="noopener noreferrer"&gt;Azure Storage Queues&lt;/a&gt;. Once nice side effect of using a queue for animations is that we don't need a database at all! This simplifies the code &lt;em&gt;and&lt;/em&gt; improves security and privacy of user data (there's nothing to leak if it doesn't exist).&lt;/p&gt;

&lt;p&gt;The last piece is the controller code running on the Raspberry Pi. This code is the smallest piece of code, and mostly just glues IoT Hub to the &lt;a href="https://github.com/nebrius/RVL-Node" rel="noopener noreferrer"&gt;RVL-Node&lt;/a&gt; package I wrote to communicate with the ESP8266s.&lt;/p&gt;

&lt;p&gt;All of the code for this project is written using &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;. The web UIs are written using &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React.js&lt;/a&gt; and &lt;a href="https://redux.js.org/" rel="noopener noreferrer"&gt;Redux&lt;/a&gt; as well. The RVL-Node module is written with a combination of TypeScript for the Node.js side of things, and C++ via Web Assembly for the logic side of things.&lt;/p&gt;

&lt;p&gt;All of these pieces together should create a fun, unique booth experience. I can't wait to show it to you all!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>azure</category>
      <category>serverless</category>
      <category>iot</category>
    </item>
    <item>
      <title>Passing structured data between C++ and JavaScript in Web Assembly</title>
      <dc:creator>Bryan Hughes</dc:creator>
      <pubDate>Mon, 22 Apr 2019 16:53:38 +0000</pubDate>
      <link>https://forem.com/azure/passing-structured-data-from-c-to-javascript-in-web-assembly-1i0p</link>
      <guid>https://forem.com/azure/passing-structured-data-from-c-to-javascript-in-web-assembly-1i0p</guid>
      <description>&lt;p&gt;I recently finished getting the &lt;a href="https://github.com/nebrius/RaverLightsMessaging"&gt;messaging stack&lt;/a&gt; of my &lt;a href="https://github.com/nebrius/raver-lights"&gt;wireless LED control system&lt;/a&gt; running in Node.js via Web Assembly (WASM for short). The last major hurdle I encountered was how to pass a lot of structured data between JavaScript and C++.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Scenario
&lt;/h1&gt;

&lt;p&gt;The core data that is passed around through my messaging stack is a set of control parameters needed to control LED animations. This information is defined in C++ using the following structs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define NUM_WAVES 4
&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;RVLWaveChannel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;int8_t&lt;/span&gt; &lt;span class="n"&gt;w_t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;int8_t&lt;/span&gt; &lt;span class="n"&gt;w_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;int8_t&lt;/span&gt; &lt;span class="n"&gt;phi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;RVLWave&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;RVLWaveChannel&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;RVLWaveChannel&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;RVLWaveChannel&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;RVLWaveChannel&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;RVLWaveSettings&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;timePeriod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;distancePeriod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;RVLWave&lt;/span&gt; &lt;span class="n"&gt;waves&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NUM_WAVES&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My animation algorithm uses a bunch of coefficients to calculate a series of superimposed sin waves. The details of how this works are for another day though, just know that it looks really really pretty! What you &lt;em&gt;do&lt;/em&gt; need to know for this blog post is that there are 82 (!!) numerical values that need to be passed from JavaScript to C++, and vice versa.&lt;/p&gt;

&lt;p&gt;As I mentioned in the previous post in this series, you can only pass numbers between C++ and JavaScript in WASM. This structured data &lt;em&gt;is&lt;/em&gt; numerical, but it's also structured. We must preserve this structure as well as the numerical values when passing data around.&lt;/p&gt;

&lt;p&gt;We could implement a function that takes 82 arguments...but I mean, c'mon, really? I just &lt;em&gt;know&lt;/em&gt; I'd mess it up! This approach would also make it really hard to update if the data changed. So we need something else. I thought about serializing to a JSON string and then deserializing it, but that takes a lot of work, processing time, and code bloat on the C++ side.&lt;/p&gt;

&lt;p&gt;What I needed was something clever...&lt;/p&gt;

&lt;h1&gt;
  
  
  My Solution
&lt;/h1&gt;

&lt;p&gt;And clever was what I found! I remembered that structs in C/C++ are laid out in memory in a deterministic manner. I realized that with this knowledge, I could directly marshal and unmarshal the data from the memory array in JavaScript, just like I did with strings!&lt;/p&gt;

&lt;p&gt;To illustrate what I'm talking about, let's take a very simple struct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;MyStruct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x12&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x3456&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x789ABCDE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;MyStruct&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we inspect the memory that &lt;code&gt;str&lt;/code&gt; points to (e.g. the numerical value of &lt;code&gt;&amp;amp;str&lt;/code&gt; in C/C++ parlance), we will see the following:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;str + 0&lt;/th&gt;
&lt;th&gt;str + 1&lt;/th&gt;
&lt;th&gt;str + 2&lt;/th&gt;
&lt;th&gt;str + 3&lt;/th&gt;
&lt;th&gt;str + 4&lt;/th&gt;
&lt;th&gt;str + 5&lt;/th&gt;
&lt;th&gt;str + 6&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0x12&lt;/td&gt;
&lt;td&gt;0x34&lt;/td&gt;
&lt;td&gt;0x56&lt;/td&gt;
&lt;td&gt;0x78&lt;/td&gt;
&lt;td&gt;0x9A&lt;/td&gt;
&lt;td&gt;0xBC&lt;/td&gt;
&lt;td&gt;0xDE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;By using the &lt;code&gt;sizeof()&lt;/code&gt; operator in C++, we know that this struct is 7 bytes large, which matches the layout above. We can also see that the values are stacked right next to each other in memory! All we need to know is the "memory offset" of each value relative to the base pointer, i.e. the &lt;code&gt;+ n&lt;/code&gt; part in the table.&lt;/p&gt;

&lt;p&gt;So how do we determine this offset? C/C++ always arranges these properties in memory in the order they are declared in the struct in the source code. In this example, &lt;code&gt;a&lt;/code&gt; comes first, followed by &lt;code&gt;b&lt;/code&gt;, followed by &lt;code&gt;c&lt;/code&gt;, because I declared them in that order in the code. If we switched the order of &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;c&lt;/code&gt; so that &lt;code&gt;b&lt;/code&gt; was at the end of the source code, then &lt;code&gt;b&lt;/code&gt; would also be at the end of the memory block.&lt;/p&gt;

&lt;p&gt;This means that we can calculate each offset summing up the size of every entry that came before it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating the calculation of offsets
&lt;/h2&gt;

&lt;p&gt;Calculating these by hand is error prone though, &lt;em&gt;especially&lt;/em&gt; when structs reference other structs as I do. I would also have to recalculate these offsets if I ever changed the data in the structs. This is a &lt;em&gt;perfect&lt;/em&gt; opportunity to automate the process with a build-time script!&lt;/p&gt;

&lt;p&gt;You can see the (admittedly poorly commented) &lt;a href="https://github.com/nebrius/RVL-Node/blob/master/scripts/wave.js"&gt;Node.js script I wrote on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The first thing I did was write a quick-n-dirty C++ parser using regex's. This parse produces a data structure that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;structs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;RVLWaveChannel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uint8_t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uint8_t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;w_t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;int8_t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;w_x&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;int8_t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;phi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;int8_t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;RVLWave&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RVLWaveChannel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;s&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RVLWaveChannel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;v&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RVLWaveChannel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RVLWaveChannel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;RVLWaveSettings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timePeriod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uint8_t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;distancePeriod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uint8_t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;waves&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;array&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;subType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RVLWave&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;arraySize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have a representation of the C++ structs in JavaScript. We're not quite ready to start calculating offsets just yet though. We have references in two of our structs to other structs, and we also have an array. When this struct is instantiated in C++, these different structs and arrays aren't represented as pointers to multiple memory blocks. Rather, the structs and arrays are "flattened" such that they all sit in a single 82 byte memory block.&lt;/p&gt;

&lt;p&gt;To represent this flattening in memory accurately, we must flatted our own representation of these structs and arrays too. I accomplished this by writing a while loop that iterates through each entry in the "root" struct (&lt;code&gt;RVLWaveSettings&lt;/code&gt; in this case). We then replace any entry whose &lt;code&gt;type&lt;/code&gt; value is not a primitive from &lt;code&gt;stdint.h&lt;/code&gt; (e.g. something of the form &lt;code&gt;[u?]int[8|16|32]_t&lt;/code&gt;) with it's "referenced" type. The way we do this replacement depends on whether it's a struct or an array. The while loop keeps running until there are no more replacements to be made.&lt;/p&gt;

&lt;p&gt;When the loop encounters an array of items, it "unrolls" the array. In other words, it replaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;waves&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;array&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RVLWave&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arraySize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;waves[0]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RVLWave&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;waves[1]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RVLWave&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;waves[2]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RVLWave&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;waves[3]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RVLWave&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When each loop of the iteration encounters a struct type, it replaces the reference to the struct with the entire entry of the struct. In other words, it replaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;waves[0]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RVLWave&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;waves[0].h&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RVLWaveChannel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;waves[0].s&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RVLWaveChannel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;waves[0].v&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RVLWaveChannel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;waves[0].a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RVLWaveChannel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we keep running this algorithm, we eventually end up with a set of entries that look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;timePeriod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;uint8_t&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;distancePeriod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;uint8_t&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;waves[0].h.a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;uint8_t&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;waves[0].h.b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;uint8_t&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;waves[0].h.w_t&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;int8_t&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;waves[0].h.w_x&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;int8_t&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;waves[0].h.phi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;int8_t&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;waves[0].s.a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;uint8_t&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, we can now loop through and calculate the offsets! I iterate through each entry and keep a running sum of the sizes, which is the memory offset for each entry. I then write this information to a JSON file that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"totalSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;82&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"entryDictionary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"timePeriod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"timePeriod"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uint8_t"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"initialValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"distancePeriod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"distancePeriod"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uint8_t"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"initialValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"waves[0].h.a"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"waves[0].h.a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uint8_t"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"initialValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using offsets to read from a C++ struct in JavaScript
&lt;/h2&gt;

&lt;p&gt;Now that we have our offsets, we can finally start passing data back and forth! Let's start by talking about how we read data from C++ into JavaScript. We start the same as we did with strings: by creating a Node.js &lt;code&gt;Buffer&lt;/code&gt; object that represents the area of memory containing the struct we want to read. Then we iterate through each element in the offset data and read the value at the given offset:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;waveSettingsPointer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;structData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;totalSize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entryName&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;structData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entryDictionary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;structEntry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;structData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entryDictionary&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;entryName&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;structEntry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uint8_t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readUInt8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;structEntry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;int8_t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readInt8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;structEntry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uint16_t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readUInt16BE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;structEntry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;int16_t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readInt16BE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;structEntry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uint32_t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readUInt32BE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;structEntry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;int32_t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readInt32BE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;structEntry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unexpected struct type "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;structEntry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// Assign the value we just read to a JavaScript mirror object&lt;/span&gt;
  &lt;span class="c1"&gt;// using some dense code I'd rather not show here :-P&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then end up with a data structure in JavaScript defined using the following TypeScript interfaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IWaveChannel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Default 0&lt;/span&gt;
  &lt;span class="nl"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Default 0&lt;/span&gt;
  &lt;span class="nl"&gt;w_t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Default 0&lt;/span&gt;
  &lt;span class="nl"&gt;w_x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Default 0&lt;/span&gt;
  &lt;span class="nl"&gt;phi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Default 0&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IWave&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;h&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IWaveChannel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IWaveChannel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IWaveChannel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IWaveChannel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IWaveParameters&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;timePeriod&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Default 255&lt;/span&gt;
  &lt;span class="nl"&gt;distancePeriod&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Default 32&lt;/span&gt;
  &lt;span class="nl"&gt;waves&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IWave&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks familiar, right?&lt;/p&gt;

&lt;p&gt;Writing to a C++ struct from JavaScript is effectively the reverse of the above. To see all the code that does the marshalling and unmarshalling, check out &lt;a href="https://github.com/nebrius/RVL-Node/blob/master/src/bridge.ts"&gt;bridge.ts on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And that's that, we can now pass structs from C++ into JavaScript and vice versa! It may sound like a whole lot of work for something that you might think would be simple, but that's kinda turning out to be par for the course with WASM. Regardless, this mechanism marks the next big step towards integrating this system with &lt;a href="https://docs.microsoft.com/en-us/azure/iot-edge/?WT.mc_id=devto-blog-brhugh"&gt;Azure IoT Edge&lt;/a&gt; via Node.js!&lt;/p&gt;

&lt;p&gt;If I have time in the future, I'd love to beef up my parsing script to use a proper C++ AST parser so it can work with a wider range of code, and publish all of this as an easy-to-consume module on npm.&lt;/p&gt;

&lt;p&gt;You can check out the complete code for the WASM powered Node.js messaging library in the &lt;a href="https://github.com/nebrius/RVL-Node"&gt;RVL-Node repository on GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>node</category>
      <category>webassembly</category>
    </item>
    <item>
      <title>Passing strings from C++ to JavaScript in Web Assembly</title>
      <dc:creator>Bryan Hughes</dc:creator>
      <pubDate>Thu, 21 Mar 2019 19:04:52 +0000</pubDate>
      <link>https://forem.com/azure/passing-strings-from-c-to-javascript-in-web-assembly-1p01</link>
      <guid>https://forem.com/azure/passing-strings-from-c-to-javascript-in-web-assembly-1p01</guid>
      <description>&lt;p&gt;I'm moving right along with my experiments of getting the &lt;a href="https://github.com/nebrius/RaverLightsMessaging"&gt;messaging stack&lt;/a&gt; of my &lt;a href="https://github.com/nebrius/raver-lights"&gt;wireless LED control system&lt;/a&gt; running in Node.js via Web Assembly (WASM for short). I'm now ready to start integrating the stack into a Node.js library.&lt;/p&gt;

&lt;p&gt;The very first thing I decided to wire up was some logging functionality. This meant passing strings from C++ to JavaScript. Sounds straightfoward, right? I thought so until I spent a day and a half struggling to get it to work 😅.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Scenario
&lt;/h1&gt;

&lt;p&gt;You can only pass numbers between JavaScript and WASM. This is just how the runtime is designed. So how do you pass more complex data?&lt;/p&gt;

&lt;p&gt;There is some &lt;a href="https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html"&gt;emscripten documentation on interacting with code across languages&lt;/a&gt; that discusses how to do just that. If you're fully immersed in the emscripten world, then you can use the functions &lt;code&gt;ccall&lt;/code&gt; and &lt;code&gt;cwrap&lt;/code&gt; to neatly and tidily pass strings from one language to another. There's a catch though: you must be running a full C++ application to make use of these functions, not just a library.&lt;/p&gt;

&lt;p&gt;I tried to hack the output so I could tie into these functions without making it a full application, similar to how I &lt;a href="https://dev.to/azure/embedding-emscripten-in-a-nodejs-library-3hdm"&gt;hacked the output&lt;/a&gt; to tie into emscripten's WASM bootstrap code. It didn't work this time though. emscripten is set up so that these functions are only available once &lt;code&gt;int main() {}&lt;/code&gt; has been run in C++ land. I don't have a main function though, since this is a library. Even adding an empty main function didn't work for some reason. emscripten threw an error stating that &lt;code&gt;ccall&lt;/code&gt; is not available until the app has been initialized and &lt;code&gt;main&lt;/code&gt; had been run.&lt;/p&gt;

&lt;p&gt;So back to the drawing board. I searched high and low for other sorts of emscripten tricks, but no such luck. Then it hit me! I was &lt;em&gt;way&lt;/em&gt; over-complicating the problem.&lt;/p&gt;

&lt;p&gt;WASM creates a chunk of memory &lt;em&gt;within&lt;/em&gt; JavaScript for its use. This memory chunk is created by calling &lt;code&gt;const memory = new WebAssembly.Memory({ initial: 256, maximum: 256 })&lt;/code&gt;. A &lt;code&gt;WebAssembly.Memory&lt;/code&gt; instance is a wrapper around an &lt;code&gt;ArrayBuffer&lt;/code&gt;, and exposes this buffer to us via the &lt;code&gt;buffer&lt;/code&gt; property on the memory instance. This is a long winded way of saying that WASM memory is just a typed array that we can access!&lt;/p&gt;

&lt;h1&gt;
  
  
  The Solution
&lt;/h1&gt;

&lt;p&gt;You might have read that last paragraph and thought "ok, cool, but what does that have to do with strings?" In C, strings are typically defined as a character array, e.g. &lt;code&gt;const char* myString&lt;/code&gt;. &lt;code&gt;const char*&lt;/code&gt; indicates that we have an array of characters, which is really an array of signed 8-bit integers. This means we can look at where the string is stored in the typed array buffer mentioned above, and interpret a contiguous block of memory as the array of characters relative to the string's memory pointer. A pointer is, at a high level, an index into a block of memory representing a value. We can represent a string in memory with a pointer called &lt;code&gt;str&lt;/code&gt; as such:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;str&lt;/th&gt;
&lt;th&gt;str + 1&lt;/th&gt;
&lt;th&gt;str + 2&lt;/th&gt;
&lt;th&gt;str + 3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;72&lt;/td&gt;
&lt;td&gt;105&lt;/td&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This block of memory forms the string &lt;code&gt;"Hi!"&lt;/code&gt;. See how there's a "fourth character" with a value of &lt;code&gt;0&lt;/code&gt;? This is what we call a "null terminator," which signifies the end of the string in memory. It's often easier to work explicitly with string length instead of looping through memory looking for a &lt;code&gt;0&lt;/code&gt;. We can get the length of any string in C/C++ with the &lt;code&gt;strlen&lt;/code&gt; function. With a pointer and string length in hand, we can iterate over the memory and reconstruct the string with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromCharCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we're ready to write the code to bind them together! First, let's write the following C++ to use a JavaScript function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="s"&gt;"C"&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;jsPrintString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello from C++!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;jsPrintString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the first &lt;code&gt;extern "C"&lt;/code&gt; line. This does two things: 1) defines the function signature for a function named &lt;code&gt;jsPrintString&lt;/code&gt; that we will implement in JavaScript, and 2) tells the compiler to use C name mangling instead of C++ name mangling. C and C++ compilers change the name of function signatures so that overloaded versions can be easily identified. This is a simple algorithm in C because it doesn't allow much overloading, and only prepends a &lt;code&gt;_&lt;/code&gt; to the name. C++ is a lot more complicated though, and you can end up with names like &lt;code&gt;_Z16RVLMessagingLoopv&lt;/code&gt; for a function called &lt;code&gt;RVLMessagingLoop&lt;/code&gt; in code. We'll see why this is important in a minute.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Make sure to add &lt;code&gt;-s ERROR_ON_UNDEFINED_SYMBOLS=0&lt;/code&gt; to your &lt;code&gt;em++&lt;/code&gt; build command. This will prevent the compiler from erroring when a defined function's implementation cannot be found in C++. This is expected since the function is defined in JavaScript, not C++. Note: be &lt;em&gt;careful&lt;/em&gt; with this option, as you may miss actual issues in your C++ code with this option enabled. Always be sure to compare the list of symbols it didn't find with what you expect not to be found.&lt;/p&gt;

&lt;p&gt;Then we have our &lt;code&gt;print&lt;/code&gt; function, which will invoke the JavaScript function. We define a character array with &lt;code&gt;const char*&lt;/code&gt; and assign it a string value. &lt;code&gt;str&lt;/code&gt; is now a pointer to the string in memory. Pointers are also numbers! This means we can pass the pointer straight from C++ to JavaScript without having to do anything special.&lt;/p&gt;

&lt;p&gt;Now it's time to modify the JavaScript code. We're going to wrap our string reconstruction code in a function called &lt;code&gt;handlePrintString&lt;/code&gt;. Then, we inject it into C++ code by modifying the &lt;code&gt;env&lt;/code&gt; object we pass to the WASM instantiation. We assign this function to the &lt;code&gt;env&lt;/code&gt; object with the key &lt;code&gt;_jsPrintString&lt;/code&gt; (note the leading underscore). This name in &lt;code&gt;env&lt;/code&gt; is the &lt;em&gt;mangled&lt;/em&gt; name of the function in C/C++. This is why we want to use C mangling instead of C++ mangling. Finally, we can invoke the &lt;code&gt;print&lt;/code&gt; function in C++ from JavaScript, which calls back into JavaScript to log the string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handlePrintString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromCharCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;_jsPrintString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;handlePrintString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instantiate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_print&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there we have it, we can now passing strings from C++ into JavaScript! It may sound small, but this marks a big step forward towards integrating this system with &lt;a href="https://docs.microsoft.com/en-us/azure/iot-edge/?WT.mc_id=devto-blog-brhugh"&gt;Azure IoT Edge&lt;/a&gt; via Node.js.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>node</category>
      <category>webassembly</category>
    </item>
    <item>
      <title>Embedding emscripten in a Node.js library</title>
      <dc:creator>Bryan Hughes</dc:creator>
      <pubDate>Fri, 15 Mar 2019 20:42:27 +0000</pubDate>
      <link>https://forem.com/azure/embedding-emscripten-in-a-nodejs-library-3hdm</link>
      <guid>https://forem.com/azure/embedding-emscripten-in-a-nodejs-library-3hdm</guid>
      <description>&lt;p&gt;I've been experimenting with Web Assembly lately, and right now I'm in the early stages of getting the &lt;a href="https://github.com/nebrius/RaverLightsMessaging"&gt;messaging stack&lt;/a&gt; of my &lt;a href="https://github.com/nebrius/raver-lights"&gt;wireless LED control system&lt;/a&gt; running in Node.js via WASM. I've gotten it up and running (yay!), but it's pretty hacky right now (boo!).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Scenario
&lt;/h2&gt;

&lt;p&gt;My library is written in C++. I intentionally avoided using anything from the C++ Standard Library and instead used the C Standard Library exclusively (it's more portable and I suspect less complicated to compile). Either way though, both of these standard libraries are &lt;em&gt;runtime&lt;/em&gt; libraries that need to be compiled in to the output. If you're a JavaScript developer and have no idea what I'm talking about, imagine if jQuery or Underscore/Lodash were defined as part of the JavaScript spec and were bundled with Node.js, but were still separate libraries. That's the C/C++ Standard Libraries.&lt;/p&gt;

&lt;p&gt;All C++ compilers come with these libraries built-in, and you don't have to do anything special to use them. emscripten comes with implementation for these as well, but IME they're still tricky to use. You have to change the compile flags. Specifically, you have to remove the &lt;code&gt;-s ONLY_MY_CODE=1&lt;/code&gt; flag that I mentioned in my &lt;a href="https://dev.to/azure/experimenting-with-web-assembly-and-nodejs-40f4"&gt;previous blog post on WASM&lt;/a&gt;. If this is the only change you make to everything in that post, your app will crash with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[LinkError: WebAssembly Instantiation: Import #1 module="env" function="nullFunc_ii" error: function import requires a callable]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uhm, excuse me, what exactly is &lt;code&gt;nullFunc_ii&lt;/code&gt; and why should I care?&lt;/p&gt;

&lt;p&gt;So here's what's going on, to the best of my understanding. emscripten compiles your code and injects any and all runtime libraries necessary to run a C++ application. This includes the aforementioned standard libraries, but also includes some other things. Most notably, emscripten injects some runtime libraries to handle things like stack overflows, exception handling, segfaults, etc. I'm about 75% certain that the &lt;code&gt;nullFunc_xxx&lt;/code&gt; methods are part of the latter.&lt;/p&gt;

&lt;p&gt;These methods are all defined in &lt;em&gt;JavaScript&lt;/em&gt;, not C++, and so are not included in the &lt;code&gt;output.wasm&lt;/code&gt; file. Instead, they're included with a JavaScript runtime file called &lt;code&gt;output.js&lt;/code&gt; (given my &lt;code&gt;-o&lt;/code&gt; flag value).&lt;/p&gt;

&lt;h2&gt;
  
  
  My Hacky Solution
&lt;/h2&gt;

&lt;p&gt;So how did I get around this? My first step was to check out the emscripten docs on &lt;a href="https://emscripten.org/docs/compiling/Building-Projects.html#emscripten-build-output-files"&gt;output files and formats&lt;/a&gt; and the various &lt;a href="https://github.com/emscripten-core/emscripten/blob/master/src/settings.js"&gt;emscripten specific config flags&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As far as I can tell, what I want to do isn't possible. emscripten allows you to either compile code on it's own (via the &lt;code&gt;-s ONLY_MY_CODE=1&lt;/code&gt; flag), or to compile a complete application that includes a &lt;code&gt;void main() {}&lt;/code&gt; (i.e. &lt;em&gt;not&lt;/em&gt; a library). Uhmmm...ok...?&lt;/p&gt;

&lt;p&gt;After a lot of trial and error, I found a &lt;em&gt;really hacky&lt;/em&gt; solution that seems to work.&lt;/p&gt;

&lt;p&gt;First, here's my complete compile command I'm now using (note: you can ignore the &lt;code&gt;ERROR_ON_UNDEFINED_SYMBOLS&lt;/code&gt; part, I'll talk about that in a later post):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;em++ &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nv"&gt;WASM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nv"&gt;ERROR_ON_UNDEFINED_SYMBOLS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nv"&gt;EXPORTED_FUNCTIONS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'_init'&lt;/span&gt;,&lt;span class="s1"&gt;'_loop'&lt;/span&gt;,&lt;span class="s1"&gt;'_setWaveParameters'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt; &lt;span class="nt"&gt;-std&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;c++11 &lt;span class="nt"&gt;-Isrc&lt;/span&gt; &lt;span class="nt"&gt;-g4&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; js-dist/output.js js/&lt;span class="k"&gt;*&lt;/span&gt;.cpp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note how we have &lt;code&gt;-o js-dist/output.js&lt;/code&gt; in the command. This tells emscripten to generate a JavaScript runtime file. This file is &lt;em&gt;intended&lt;/em&gt; to be used as a "main" file, i.e. an &lt;em&gt;entire&lt;/em&gt; application. We want to use it as a library though, not an application. There are a lot of things in here we need though, most notably two variables it creates called &lt;code&gt;asmGlobalArg&lt;/code&gt; and &lt;code&gt;asmLibraryArg&lt;/code&gt;. These variables define all of the &lt;code&gt;nullFunc_xxx&lt;/code&gt; methods, among others. These variables are not exported in any way though, and as far as I can tell are not meant to be consumed directly.&lt;/p&gt;

&lt;p&gt;We're going to do it anways, damn the consequences! I wrote a script to automatically hack this file with the following contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;writeFileSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;join&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;OUTPUT_FILE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;..&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;js-dist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;output.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;OUTPUT_FILE&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;var asmGlobalArg =&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;var asmGlobalArg = module.exports.asmGlobalArg =&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;var asmLibraryArg =&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;var asmLibraryArg = module.exports.asmLibraryArg =&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;OUTPUT_FILE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can import these variables into our main file (which is now written in TypeScript FWIW):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;readFile&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;join&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;asmGlobalArg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;asmLibraryArg&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./output&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;wasmExports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ResultObject&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Memory&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;maximum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;output.wasm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;readErr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;asmLibraryArg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;initial&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;maximum&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;element&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;anyfunc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;__table_base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;__memory_base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;STACKTOP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;STACK_MAX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;byteLength&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;asmGlobalArg&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instantiate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;wasmExports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;wasmExports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deviceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it works! But it's also pretty ugly IMO. I'm excited though, cause I'm one step closer to integrating this system with &lt;a href="https://docs.microsoft.com/en-us/azure/iot-edge/?WT.mc_id=devto-blog-brhugh"&gt;Azure IoT Edge&lt;/a&gt; so I can control my LEDs from the cloud!&lt;/p&gt;

&lt;h2&gt;
  
  
  Question for all of you
&lt;/h2&gt;

&lt;p&gt;Am I missing something here? Is there a proper way to do this? I find it hard to believe that emscripten doesn't have an option for compiling a library that includes all the necessary runtime libraries, but I can't seem to figure out how.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>webassembly</category>
      <category>question</category>
    </item>
    <item>
      <title>Experimenting with Web Assembly and Node.js</title>
      <dc:creator>Bryan Hughes</dc:creator>
      <pubDate>Tue, 12 Mar 2019 23:42:50 +0000</pubDate>
      <link>https://forem.com/azure/experimenting-with-web-assembly-and-nodejs-40f4</link>
      <guid>https://forem.com/azure/experimenting-with-web-assembly-and-nodejs-40f4</guid>
      <description>&lt;p&gt;I've been wanting to play around with &lt;a href="https://webassembly.org/"&gt;Web Assembly&lt;/a&gt; for a while, and finally had a chance to. Since I'm a mostly Node.js developer, I wanted to play around with it here instead of in the browser. There's not a lof of documentation on Web Assembly though, and the APIs are changing rapidly. I finally got it to work though, and here's how I did it.&lt;/p&gt;

&lt;p&gt;I mostly followed the &lt;a href="https://emscripten.org/docs/getting_started/index.html"&gt;emscripten Getting Started guide&lt;/a&gt;, and tweaked it to fit both Node.js and to account for parts of this doc that are out of date.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing emscripten
&lt;/h2&gt;

&lt;p&gt;The first step is to install emscripten, which is well documented on &lt;a href="https://emscripten.org/docs/getting_started/downloads.html"&gt;emscripten's website&lt;/a&gt;. I installed it inside of Windows Subsystems for Linux running Ubuntu, so YMMV if you're using a different OS.&lt;/p&gt;

&lt;p&gt;The first step is to install some dependencies. This takes a while, so I recommend brewing a nice cup of tea during this time. I chose a nice Silver Needle this time around :)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install Node.js using NodeSource's Ubuntu PPA, if not already installed&lt;/span&gt;
curl &lt;span class="nt"&gt;-sL&lt;/span&gt; https://deb.nodesource.com/setup_10.x | &lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; bash -

&lt;span class="c"&gt;# Install dependencies, as defined in emscripten's getting started guide&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;python2.7 nodejs cmake default-jre
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we're ready to install emscripten itself. This also takes some time, so enjoy some more tea.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/emscripten-core/emsdk.git
&lt;span class="nb"&gt;cd &lt;/span&gt;emsdk
./emsdk &lt;span class="nb"&gt;install &lt;/span&gt;latest
./emsdk activate latest
&lt;span class="nb"&gt;source&lt;/span&gt; ./emsdk_env.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I ran into a bit of an issue with this approach. I don't know if I made a mistake, or things are just locked in. Either way, emscripten installed version 8.x.x of Node.js on it's own and overrode my 10.x.x install of Node.js. Since I'm using async/await for my Node.js code (which requires Node 10 in practice, if not in theory), I needed to manually override this by editing &lt;code&gt;~/.emscripten&lt;/code&gt; so the following line matches the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;NODE_JS&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'/usr/bin/node'&lt;/span&gt; &lt;span class="c"&gt;# This line used to have a super long path to the emsdk directory
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I never ran into any problems swapping out the version of Node.js that emscripten expected, but as always, YMMV.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the code
&lt;/h2&gt;

&lt;p&gt;First, I created a very simple C file, courtesy of an &lt;a href="https://www.codepool.biz/use-webassembly-node-js.html"&gt;older blog post at Dynamsoft&lt;/a&gt;, named &lt;code&gt;test.c&lt;/code&gt;. (Note: the instructions in this blog post no longer work).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, I created the JavaScript file that consumes this C module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;util&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;util&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createWebAssembly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Memory&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;maximum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;abortStackOverflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`overflow: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;maximum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;anyfunc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="na"&gt;__table_base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;__memory_base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;STACKTOP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;STACK_MAX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;byteLength&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;WebAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instantiate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;createWebAssembly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./output.wasm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;util&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things to note about this JavaScript code. First, the code is a masheup of the code from the Dynamsoft blog post and the emscripten getting started guide. I recommend reading the emscripten getting started guide for an in-depth explanation of what's going on here. The next thing to note is the &lt;code&gt;__table_base&lt;/code&gt; and &lt;code&gt;__memory_base&lt;/code&gt; entries. These are named &lt;code&gt;tableBase&lt;/code&gt; and &lt;code&gt;memoryBase&lt;/code&gt; in the emscripten documentation and in almost all other documentation I've found, but crashes when run. I'm guessing the API changed very recently. Hat tip to &lt;a href="https://gist.github.com/kripken/59c67556dc03bb6d57052fedef1e61ab#gistcomment-2779875"&gt;this gist&lt;/a&gt; for pointing me in the right direction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the code
&lt;/h2&gt;

&lt;p&gt;Now that we've written our files, it's time to run the code. First we compile this code with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;emcc &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nv"&gt;WASM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nv"&gt;ONLY_MY_CODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nv"&gt;EXPORTED_FUNCTIONS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"['_add']"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; output.js &lt;span class="k"&gt;*&lt;/span&gt;.c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will generate the file &lt;code&gt;output.wasm&lt;/code&gt; that's referenced in the JavaScript code. Now we're ready to run our code!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; node index.js
{ instance: Instance [WebAssembly.Instance] {},
  module: Module [WebAssembly.Module] {} }
18
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it works! We can indeed add 9 and 9 together to get 18, calling from JavaScript to C++ and back again, all using Web Assembly!&lt;/p&gt;

&lt;p&gt;My next step is to take the &lt;a href="https://github.com/nebrius/RaverLightsMessaging"&gt;C++ messaging stack&lt;/a&gt; from my &lt;a href="https://github.com/nebrius/raver-lights"&gt;LED synchronization and animation project&lt;/a&gt;, wrap it in Web Assembly so Node.js can talk to my boards, and integrate it with &lt;a href="https://docs.microsoft.com/en-us/azure/iot-edge/?WT.mc_id=devto-blog-brhugh"&gt;Azure IoT Edge&lt;/a&gt; so I can control my LEDs from the cloud!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>webassembly</category>
    </item>
    <item>
      <title>twitter-replies-parser - A Tool for Converting Twitter Replies into JSON</title>
      <dc:creator>Bryan Hughes</dc:creator>
      <pubDate>Thu, 07 Mar 2019 19:24:59 +0000</pubDate>
      <link>https://forem.com/azure/twitter-replies-parser---a-tool-for-converting-twitter-replies-into-json-3j4a</link>
      <guid>https://forem.com/azure/twitter-replies-parser---a-tool-for-converting-twitter-replies-into-json-3j4a</guid>
      <description>&lt;p&gt;Some of my teammates and I recently asked Node.js folks on Twitter what tools they used and why the liked them. We're collecting this so we can help our product teams at Microsoft create better &lt;a href="https://docs.microsoft.com/en-us/javascript/azure/?view=azure-node-latest&amp;amp;wt.mc_id=devto-blog-brhugh" rel="noopener noreferrer"&gt;Node.js tools for Azure&lt;/a&gt; that serve you, the community. Turns out, lots of folks have a lot of great opinions and feedback on this subject. This is great!&lt;/p&gt;

&lt;p&gt;What's not so great is that we had so many replies we couldn't just copy-paste them from the web client 😱. So what to do? Write some JavaScript, of course!&lt;/p&gt;

&lt;p&gt;It was a little easier said than done though. As it turns out, Twitter doesn't have any APIs available to get the replies to a tweet. Instead, I had to use the search API and then create the reply tree by hand. With a little coding work and a handful of recursive calls, I got it all working to a high degree of accuracy. Due to the approach used, it's not 100% accurate. I noticed about 2-3 tweets were missing out of the ~60 replies to &lt;a href="https://twitter.com/nebrius/status/1102630156718370816" rel="noopener noreferrer"&gt;my request for feedback&lt;/a&gt;, but close enough!&lt;/p&gt;

&lt;p&gt;This tool is a Node.js application that spins up a web server with a simple web app for entering the URL of the tweet you want to get the replies to. It's definitely not pretty, but get's the job done:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fe7ktanuu8o88ddl390wh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fe7ktanuu8o88ddl390wh.jpg" alt="Screenshot of the web UI for Twitter Replies Parser"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can check out the tool on &lt;a href="https://github.com/nebrius/twitter-replies-parser" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, which is released under the MIT open source license. I'd love to hear what you think, and if you run into any issues using it.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>twitter</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Writing Unit Tests For A Rewrite: A Case Study</title>
      <dc:creator>Bryan Hughes</dc:creator>
      <pubDate>Tue, 26 Feb 2019 18:56:01 +0000</pubDate>
      <link>https://forem.com/azure/writing-unit-tests-for-a-rewrite-a-casestudy-466m</link>
      <guid>https://forem.com/azure/writing-unit-tests-for-a-rewrite-a-casestudy-466m</guid>
      <description>&lt;p&gt;&lt;em&gt;This blog post is the first post in a series that discusses my efforts to convert &lt;a href="https://github.com/nebrius/raspi-io/"&gt;Raspi IO&lt;/a&gt; to TypeScript and modernize its architecture. This blog post series will explore how to write unit tests specifically for rearchitecting or rewriting a project, how to create TypeScript base classes and functionality that is shared across multiple TypeScript and non-TypeScript projects, and how to convert an existing code base to TypeScript all in one go.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post was first published to the &lt;a href="https://medium.com/microsoftazure/converting-to-typescript-part-1-unit-tests-87c20329d6c7"&gt;Azure Medium publication&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;All codebases age and mature over time. With age brings stability, and older projects are typically more reliable as a result.&lt;/p&gt;

&lt;p&gt;However, age also brings with it creaks and groans as the original architecture struggles to keep up with modern user needs. Time also brings newer, better ways of developing these projects, and what was once cutting edge often becomes clunky and slow.&lt;/p&gt;

&lt;p&gt;So the question for these projects becomes: to rewrite, or not to rewrite? I faced such a question with my oldest project still under development: &lt;a href="https://github.com/nebrius/raspi-io/"&gt;Raspi IO&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Raspi IO is a plugin for the &lt;a href="http://johnny-five.io/"&gt;Johnny-Five&lt;/a&gt; Node.js robotics and IoT framework that enables Johnny-Five to run on the Raspberry Pi. I first created it as a monolith in 2014, but the original architecture quickly ran into limitations as I added more features. I rewrote the library the following year and split it into multiple modules. This rewrite allowed the project to scale as more features were added.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--biLeL68c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/vpw9w5fq3cr5n1q7mduh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--biLeL68c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/vpw9w5fq3cr5n1q7mduh.png" alt="Raspi IO Architecture Diagram" width="800" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Raspi IO currently consists of 11 modules. Nine of these modules comprise what I call &lt;a href="https://github.com/nebrius/raspi"&gt;Raspi.js&lt;/a&gt;, which can be used independently of Raspi IO and Johnny-Five. These modules together provide a complete API for interacting with hardware on the Raspberry Pi in a uniform way. Raspi IO and Raspi IO Core together provide a translation layer from Raspi.js to the &lt;a href="https://github.com/rwaldron/io-plugins"&gt;IO Plugin spec&lt;/a&gt; for Johnny-Five. Raspi IO Core is platform independent, and Raspi IO injects Raspi.js into Raspi IO Core to create a Raspberry Pi specific IO plugin.&lt;/p&gt;

&lt;p&gt;Over time, all of Raspi.js has been converted to TypeScript and updated to modern coding practices. Raspi IO and Raspi IO Core, however, have remained more or less unchanged for three years. This is fine for Raspi IO, which only contains 32 lines of code, but not for Raspi IO Core. Inside, there are 1000 lines of dense JavaScript, replete with hacks for strange edge cases and bugs. This codebase definitely falls under the classic case of “afraid to make changes because it might break everything.” It’s also in dire need of updating to TypeScript and modern coding conventions.&lt;/p&gt;

&lt;p&gt;With the need clear in my head, I sat down and devised a plan to rewrite Raspi IO Core without breaking it for my users. The first step in this rewrite was to implement unit tests with a high degree of code coverage, as Raspi IO Core did not have unit tests for historical reasons (unit tests involving hardware are tough).&lt;/p&gt;

&lt;p&gt;While major refactors and rewrites bring a lot of advantages to them, such as state-of-the-art best practices and modern tooling, they are inherently risky from the standpoint of breaking your users. Unit tests act as insurance to make sure that the rewrite is as transparent to users as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methodology
&lt;/h2&gt;

&lt;p&gt;So how does one implement unit tests for a project that has no unit tests and needs to be rewritten? Very methodically, and following a specification.&lt;/p&gt;

&lt;p&gt;As previously mentioned, Raspi IO Core implements a published specification called the &lt;a href="https://github.com/rwaldron/io-plugins"&gt;IO Plugin Spec&lt;/a&gt;. This spec provides a blueprint for how the module is supposed to behave, and in effect provides a blueprint for the unit tests themselves.&lt;/p&gt;

&lt;p&gt;Not all projects implement an API spec, but hopefully there are design documents or other documentation describing what the project is supposed to do. If not, then the first step in implementing unit tests is to write such a spec. It’s a lot of work, but I promise it will help tremendously down the road. In addition to making it easier to implement unit tests, it provides a place for all stakeholders, not just coders, to provide input on the project and make it better. If you’re unsure where to start, &lt;a href="https://apiguide.readthedocs.io/en/latest/build_and_publish/documentation.html"&gt;Read the Docs&lt;/a&gt; has good content on writing quality specifications.&lt;/p&gt;

&lt;p&gt;Next up was to decide on a unit testing tech stack. I decided to go with a common stack for open source Node.js modules because I’m already familiar with them, and didn’t want to learn new tools or platforms at this time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://jasmine.github.io/"&gt;Jasmine&lt;/a&gt;: a &lt;a href="https://en.wikipedia.org/wiki/Behavior-driven_development"&gt;Behavior Driven Development&lt;/a&gt; (BDD) test framework.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://istanbul.js.org/"&gt;Istanbul&lt;/a&gt;: a JavaScript &lt;a href="https://en.wikipedia.org/wiki/Code_coverage"&gt;code coverage&lt;/a&gt; tool. Code coverage tools measure how much of your codebase is executed by your unit tests, and provides a useful proxy measure of how much of your code is tested by unit tests.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://travis-ci.org/"&gt;Travis CI&lt;/a&gt;: a hosted unit testing platform that makes it easy to run unit tests on GitHub activity (e.g. when a PR is submitted, when pushing/merging to master, etc). Although not strictly required for the rewrite, it’s generally a good idea to wire up unit tests to a hosted platform such as Travis CI. This allows developers who are considering using your library to see unit test results without having to download your code and run tests themselves.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://coveralls.io/"&gt;Coveralls&lt;/a&gt;: a hosted code coverage platform that integrates with Travis CI, and provides all the value that Travis CI does, except for code coverage instead of unit tests themselves.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the specification and unit testing infrastructure in place, it was time to write my unit tests!&lt;/p&gt;

&lt;h2&gt;
  
  
  Walkthrough of a Unit Test
&lt;/h2&gt;

&lt;p&gt;To illustrate how to write an effective unit test, I’m going to do a deep-dive walkthrough for one part of the IO spec: the &lt;code&gt;digitalRead&lt;/code&gt; method. The IO Plugin spec has this to say about the &lt;code&gt;digitalRead&lt;/code&gt; method:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;digitalRead(pin, handler)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initiate a new data reading process for &lt;code&gt;pin&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The recommended new data reading frequency is greater than or equal to 200Hz. Read cycles may reduce to 50Hz per platform capability, but no less.&lt;/li&gt;
&lt;li&gt;Invoke &lt;code&gt;handler&lt;/code&gt; for all new data reads in which the data has changed from the previous data, with a single argument which is the present value read from the pin.&lt;/li&gt;
&lt;li&gt;A corresponding &lt;code&gt;digital-read-${pin}&lt;/code&gt; event is created and emitted for all new data reads in which the data has changed from the previous data, with a single argument which is the present value read from the pin (This can be used to invoke handler).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can break the things this spec says we must do down into a few different things we need to test, which will become our set of unit tests. Reading through the spec, I identified the following five tests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The third bullet point indicates we need to test reading a value via the &lt;code&gt;handler&lt;/code&gt; argument as the pin value changes over time.&lt;/li&gt;
&lt;li&gt;The fourth bullet point indicates we need to test reading a value via the &lt;code&gt;digital-read-${pin}&lt;/code&gt; event as the pin value changes over time.&lt;/li&gt;
&lt;li&gt;The second bullet point indicates we need to test that &lt;code&gt;handler&lt;/code&gt; is called at 50hz or faster.&lt;/li&gt;
&lt;li&gt;The third and fourth bullet points indicate we need to test that the method doesn’t report the same value twice in a row.&lt;/li&gt;
&lt;li&gt;Implicit in this and other parts of the spec is that we need to test that &lt;code&gt;digitalRead&lt;/code&gt; continues to read even when the mode is changed to output mode and reports the output value that was set via &lt;code&gt;digitalWrite&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we’ve identified five unit tests we want to write, the next step is to figure out &lt;em&gt;how&lt;/em&gt; to write them. At the end of the day, unit tests exist to confirm that the correct outputs are generated given a reasonably complete sampling of inputs. So the first step in any unit test is to identify the inputs and outputs.&lt;/p&gt;

&lt;p&gt;We tend to think of inputs and outputs as the arguments we pass to functions, and the values they return. These are not the only inputs that exist though. For example, if we’re testing a function that saves a value to the database, then the call to the database is also an output, in addition to what the function returns or the callback it calls. In the case of &lt;code&gt;digitalRead&lt;/code&gt;, we’re calling other modules that talk to hardware (more outputs and inputs!). In general, it’s quite common for there to be two &lt;em&gt;or more&lt;/em&gt; sets of inputs and outputs.&lt;/p&gt;

&lt;p&gt;The trick in unit testing is to figure out how to measure the inputs and outputs on the “back end” of the diagram below. Most often, this is done using &lt;a href="https://en.wikipedia.org/wiki/Mock_object"&gt;mocking&lt;/a&gt;, and is the solution I chose to use here. The architecture of Raspi IO Core makes this pretty straightforward to do because we can pass in &lt;a href="https://github.com/nebrius/raspi-io-core/blob/master/spec/mocks.js"&gt;mocked versions of all the modules in Raspi.js&lt;/a&gt;. The full set of inputs and outputs we’re testing are shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1a_e4JWj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/5pmec326r2bow6gcrcvz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1a_e4JWj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/5pmec326r2bow6gcrcvz.png" alt="All Inputs and Outputs for digitalRead Tests" width="800" height="167"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These mocked versions include a virtual implementation of hardware, and expose the inputs/outputs to this module such that we can verify them in our unit tests. For this unit test, we use the &lt;code&gt;DigitalInput&lt;/code&gt; mock, which has the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;DigitalInput&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Peripheral&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;OFF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;setMockedValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ve added an extra method called &lt;code&gt;setMockedValue&lt;/code&gt; that doesn’t exist in the real Raspi GPIO &lt;code&gt;DigitalInput&lt;/code&gt; class. This allows us to precisely control what Raspi IO Core will be reading. We also add a new property called &lt;code&gt;args&lt;/code&gt; that we can use to see what parameters were passed to the class constructor. With this in place, we can measure all of the inputs and outputs to the “back end” of the black box we’re testing.&lt;/p&gt;

&lt;p&gt;Now it’s time for the unit tests themselves. We’re going to take a look at a single unit test that tests using the callback to read the value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;can read from a pin using the `digitalRead` method&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;createInstance&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;raspi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;raspi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pinAlias&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;raspi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pinAlias&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;raspi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MODES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INPUT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;peripheral&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;raspi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getInternalPinInstances&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="nx"&gt;pin&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;numReadsRemaining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;NUM_DIGITAL_READS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;peripheral&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setMockedValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;raspi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;digitalRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pinAlias&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;numReadsRemaining&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;peripheral&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setMockedValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We start with some initialization code to get a test pin ready to read. We then call &lt;code&gt;getInternalPinInstances&lt;/code&gt;, which is a special hook method that’s only exposed when we’re running unit tests. This returns the mocked instance of &lt;code&gt;DigitalInput&lt;/code&gt; so we can access the hooks in &lt;code&gt;DigitalInput&lt;/code&gt; we discussed above.&lt;/p&gt;

&lt;p&gt;Then, we set up some state monitoring variables. Since this method is supposed to read data continuously, we must test that it can read more than once. &lt;code&gt;numReadsRemaining&lt;/code&gt; tracks how many reads we’ve performed and how many we have left to go. We toggle the value each callback since it won’t call the callback if the value doesn’t change. In each callback, we test that the value that Raspi IO Core reports is the same value that we set in the mocked &lt;code&gt;DigitalInput&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;And with that, the unit test is complete! If you’d like to see all of the unit tests that comprise the &lt;code&gt;DigitalInput&lt;/code&gt; tests, you can &lt;a href="https://github.com/nebrius/raspi-io-core/blob/master/spec/gpio.spec.js#L86-L237"&gt;find them on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;Throughout this process, I’ve learned several important lessons about unit tests and rewrites.&lt;/p&gt;

&lt;h3&gt;
  
  
  Edge cases are &lt;em&gt;more&lt;/em&gt; important than common cases.
&lt;/h3&gt;

&lt;p&gt;We test our common cases a lot, and our code is written with these common cases in mind. Edge cases, more often than not, are found through trial and error, or user reports. As such, when we’re rewriting an existing codebase, we want to make sure that we port the edge cases over as they’re much less likely to be fixed “out of the gate.” Getting unit tests to test these edge cases is the most effective way to ensure we get these edge cases included in the rewrite.&lt;/p&gt;

&lt;h3&gt;
  
  
  Always be specific, not general
&lt;/h3&gt;

&lt;p&gt;When writing unit tests, it’s easy to write something quick that more or less tests what we want. For example, if we’re testing whether or not a function throws an exception when it’s given an incorrect parameter, we could write something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`I'm not a number`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;toThrow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will indeed pass, but how do we know it passed because the &lt;code&gt;add&lt;/code&gt; method correctly detected that we tried to add two non-numbers? What if there was a legitimate bug in the code that coincidentally threw on the same inputs? We should instead write this test as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`I'm not a number`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;toThrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`non-numbers passed as arguments to "add"`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, we can ensure that it’s throwing the way we expect. This also helps us to prevent typos if we aren’t copy-pasting the error message over. This may not seem like a big deal, but sometimes user’s code depends on the content of the error message because they need to make a decision based on &lt;em&gt;which&lt;/em&gt; error is thrown. If we change our error message, we break this code. For an in-depth discussion of why error messages are important (and tricky), I recommend reading how the Node.js project itself is &lt;a href="https://medium.com/the-node-js-collection/node-js-errors-changes-you-need-to-know-about-dc8c82417f65"&gt;changing how it does error handling&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Good code coverage is more important for rewrites than it is for day-to-day development.
&lt;/h3&gt;

&lt;p&gt;In an ideal world we’d all have 100% code coverage. In practice, however, 100% code coverage is rarely ideal, and sometimes impossible. Indeed, Raspi IO Core sits at 93% coverage because most of the code not being testing is dead code. Most of this dead code is runtime code introduced by Babel itself, which is admittedly an outdated version. The rest is code that I thought was necessary but is most likely dead code in practice. There are also cases where some code is so tightly bound to something not present during testing (like, say, an external sensor), that mocking everything necessary would lead to a unit test that really is only testing the mocks, not the code itself.&lt;/p&gt;

&lt;p&gt;It’s expected not to have 100% code coverage, but it’s more important to have high code coverage for a rewrite than for day-to-day coding. This is because of statistics. During a rewrite, we are changing vast swaths of our code which end up being covered by large numbers of unit tests, and thus large numbers of edge cases. Day to day coding rarely has such far reaching changes though. As such, the chance of regressions is higher during a rewrite. Having high code coverage is the most effective way at preventing regressions in general, and so high code coverage is especially important when we’re dealing with changes that have high risk of regressions, such as a rewrite.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing unit tests against a spec also improves the spec
&lt;/h3&gt;

&lt;p&gt;As much as we want to view specifications as infallible, they’re created by humans. And just like humans who create code, humans who create specifications sometimes make mistakes and introduce bugs in the spec. Writing unit tests against a spec will often highlight areas of the spec that are ambiguous or contain errors. In creating the unit tests for Raspi IO Core, I uncovered multiple issues with the spec. In &lt;a href="https://github.com/rwaldron/io-plugins/pull/17"&gt;three&lt;/a&gt; of &lt;a href="https://github.com/rwaldron/io-plugins/pull/21"&gt;the&lt;/a&gt; &lt;a href="https://github.com/rwaldron/io-plugins/pull/19"&gt;cases&lt;/a&gt;, we simply forgot to update the spec with some new features that were added. In &lt;a href="https://github.com/rwaldron/io-plugins/issues/16"&gt;two&lt;/a&gt; other &lt;a href="https://github.com/rwaldron/io-plugins/issues/18"&gt;cases&lt;/a&gt;, the spec was ambiguous. Going through the process of writing unit tests can be a surprisingly effective way at sussing out issues in the specification.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I’ve attempted to convert Raspi IO Core to TypeScript probably 4 or 5 times in the past. Each previous attempt failed because I quickly became uncertain that I could provide a painless upgrade path for my users. Without unit tests, I was not confident in my changes. Writing these unit tests was the key missing ingredient in these previous attempts, and now I’m set to move forward with converting Raspi IO Core to TypeScript, and re-architecting major parts of it in the process.&lt;/p&gt;

&lt;p&gt;This effort has really reiterated the importance of unit tests, as well as the importance of understanding what we test, how we test it, and why.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>testing</category>
      <category>refactoring</category>
    </item>
  </channel>
</rss>
