bartblast
Creator of Hologram
Hey there! ![]()
We need help completing Elixir’s browser runtime by porting some Erlang functions to JavaScript.
Hologram automatically transpiles Elixir, but the underlying Erlang functions - the building blocks of Elixir’s stdlib - must be ported manually.
No Erlang knowledge required - just basic JS/Elixir skills and pattern-following. Tasks: 15 min to a few hours. AI tools encouraged!
Each function you port unlocks multiple Elixir stdlib functions in the browser!
Read the full blog post: https://hologram.page/blog/elixir-to-javascript-porting-initiative
Trending in News & Updates
Today we’re releasing Oban for Python. Not an Oban client in Python. Not a pythonx wrapper embedded in Elixir. Nope, it’s a fully operati...
New
I’m a bit excited to announce that Localize and friends are now at release 1.0. Even though it’s a 1.0 release, it stands on 8 years of w...
New
I’ll be using this thread to share Hologram patch release announcements. Minor releases will continue to get dedicated threads with blog ...
New
Hologram v0.11 is out! Two headline features this release. First, Elixir regexes now run in the browser. They were server-only until now,...
New
Just published search_ash 0.5.0 (with search_core 0.4.0) on Hex.
What’s new: synonyms
You can now declare a synonym dictionary per lang...
New
MdexMultilineCells is an MDEx plugin enabling multi-line cells in Markdown tables with full
inline/block Markdown rendering and automati...
New
This release unifies configuration for queues, repos, and services, swaps opaque timing integers for readable durations, and backports pe...
New
Other Trending Topics
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
There are three potential reasons for members of this forum to have a look at https://vutuv.de
You are tired or annoyed of LinkedIn.
Yo...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixir-ls
- #ai
- #elixirconf-us
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming











Showing Posts 31 to 22- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
bartblast
Update on time-related functions
While reviewing the PRs for Erlang time functions (
:os.system_time,:erlang.monotonic_time,:erlang.system_time,:erlang.time_offset,:erlang.convert_time_unit,:erlang.localtime), I realized they’re more interconnected than I initially thought.In Erlang’s time system:
Erlang System Time = Erlang Monotonic Time + Time OffsetThis means these functions should delegate to each other rather than each independently calling JS APIs. I’ve documented a unified porting strategy to ensure consistency:
Erlang Time Functions Porting Strategy
Happy to discuss if you have questions or alternative suggestions!
bartblast
Closing the loop on the
:os.type/0discussion for future reference (this reasoning applies to similar cases as well):We decided to hardcode
{:unix, :web}for the client-side implementation. This aligns with our approach in other modules like:filename, where we unify path handling and treat the Hologram client platform as Unix-based.The reasoning is twofold:
:os.type/0in Erlang/Elixir is meant to return the OS of the machine running the BEAM VM - but on the client side, our code runs in a browser sandbox, not directly on the user’s OS. Returning the actual user’s OS would be semantically incorrect and could break code that relies on:os.type/0for platform-specific behavior (like path handling).Web APIs provide a unified, platform-independent abstraction - the browser hides OS differences from JavaScript code. Since web conventions align with Unix (forward slashes for paths/URLs), choosing
{:unix, :web}is a pragmatic decision that simplifies our implementation (e.g., consistent path handling in:filenameand similar modules).For use cases where you actually need the user’s platform information (analytics, file downloaders offering platform-specific binaries, UI adaptations, etc.), we’ll expose this through a dedicated Hologram module that clearly indicates it’s about the end user’s environment rather than the execution platform.
bartblast
@tenkiller Using an external lib like
ua-parser.jswould be overkill IMO, especially when that package is ~12kb minzipped. We’re only detecting basic OS families here, not parsing detailed browser/device info.:os.type/0returns just a basic system type - in practice it’s one of these (though could you verify the complete list by checking the Erlang/OTP docs?):Unix family:
{:unix, :darwin}- macOS{:unix, :linux}- Linux{:unix, :freebsd}- FreeBSD{:unix, :openbsd}- OpenBSD{:unix, :netbsd}- NetBSD{:unix, :sunos}- Solaris/SunOS{:unix, :aix}- IBM AIXWindows family:
{:win32, :nt}- Windows NT-based systems (includes Windows XP, Vista, 7, 8, 10, 11, and Server editions)We just need some simple heuristics for the
userAgentstring - probably looking for specific words/patterns would be enough. Check out the patterns from the Elixirua_parserlib for ideas: ua_parser/priv/patterns.yml at main · beam-community/ua_parser · GitHubFor example, you could check if the userAgent contains “Mac”, “Win”, “Linux”, etc. and map those to the appropriate tuples. Should be pretty straightforward!
Re: consistency testing - it’s mostly impossible in this case since the Elixir version runs on the server (returning the server’s OS) while the JS version runs in the browser (returning the client’s OS).
So for this one:
describeblock inos_test.mjsand test various OS detections thoroughly thereos_test.exs, just add a sanity test that calls the actual Erlang:os.type/0function and asserts the returned value is one of the tuples we support on the client-sidetenkiller
UserAgent parsing is rather complicated if we rolled our own. Do you have a library recommendation, like ua-parser.js perhaps? Also, testing consistency with the JS implementation in
os_test.exsis not clear to me either.bartblast
@tenkiller For navigator, just swap out
globalThis.navigatorwith a mock object in your tests:For the implementation, the recommended fallback order is:
navigator.userAgentData.platform- modern API with clean values (“macOS”, “Windows”, “Linux”)navigator.platform- legacy but widely supported (“MacIntel”, “Win32”, “Linux x86_64”)navigator.userAgent- last resort, requires string parsingThe userAgentData API isn’t supported in Firefox or Safari, so the platform fallback will handle those browsers. You may find that parsing userAgent is rarely needed in practice.
tenkiller
@bartblast Concerning
os.type/0, I know you said you’d like it to mimic Erlang’s behavior and detect the OS platform and family via thenavigator.userAgentData, but how should I actually test this? What’s the best strategy for stubbing thewindow.navigatorobject inos_test.mjs?bartblast
Quick update: I’ve gone through all the remaining TODO Erlang functions and reviewed them. With far fewer left now, this was much more manageable!
I’ve pushed some functions to phase 2 after analyzing which Elixir stdlib functions depend on them. These deferred functions are primarily used by process-related Elixir stdlib functions, which aren’t targets for phase 1. Most of the deferred functions were ETS-related, commonly used by modules like
PartitionSupervisorandRegistry.This is your last chance to contribute – only 40 functions left to port for phase 1!
Thanks for all your contributions so far!
bartblast
That’s intentional - there’s no separate primitive “string” type in Elixir at the VM level. Elixir strings are UTF-8 encoded binaries.
Type.string()is only an internal helper Hologram uses for text segments inside bitstrings, not a public string type. You can useType.bitstring()helper for text - it will convert the text to boxed bitstring type (which includes binaries and therefore UTF-8 strings).bartblast
Looking at your PRs now, @Lucassifoni
tenkiller
I noticed that
Type.encodeMapKey()does not supportstringdata types. Is this intentional? I can extend it to support them in a separate PR, or would you rather I include that change in my upcoming:sets.to_list/1PR?For reference, here is the test I would add to
type_test.mjsafter extending it: