Skip to content

Conversation

@mward-sudo
Copy link
Contributor

@mward-sudo mward-sudo commented Dec 7, 2025

Overview

This PR implements the :erlang.exit/1 function as a JavaScript port for the Hologram project.

Closes #450

What Was Done

1. JavaScript Implementation

  • Added exit/1 function to assets/js/erlang/erlang.mjs
  • Implementation throws a HologramExitError with the provided reason
  • Positioned alphabetically between error/2 and float/1
  • Includes proper Start/End comments for compiler extraction
  • Deps comment correctly set to empty array (no dependencies)

2. New Error Type: HologramExitError

Created assets/js/errors/exit_error.mjs with a new error class that:

  • Extends the native JavaScript Error class
  • Stores the exit reason for access
  • Generates meaningful error messages
  • Follows the project's error hierarchy pattern

3. JavaScript Tests

Added comprehensive unit tests in test/javascript/erlang/erlang_test.mjs:

  • Test with atom reason (:normal)
  • Test with tuple reason ({:error, :reason})
  • Tests verify that HologramExitError is thrown with proper error handling
  • Uses standard assert.throws pattern with error constructor

4. Elixir Consistency Tests

Added server-side verification tests in test/elixir/hologram/ex_js_consistency/erlang/erlang_test.exs:

  • Test with atom reason (:normal)
  • Test with tuple reason ({:error, :reason})
  • Test with integer reason (1)
  • Uses proper try-catch-exit blocks to verify behavior matches Erlang semantics
  • Ensures client and server implementations are consistent

Design Decision: HologramExitError

A key design decision was whether to:

  1. Create a new error class (current approach)
  2. Modify HologramBoxedError to handle both error structs and arbitrary values
  3. Just throw raw values without wrapping

The new error class approach was chosen because:

  • HologramBoxedError is specifically designed for error structs with type/message extraction from struct fields
  • exit/1 can throw ANY value, not just error structs with specific structure
  • A separate error class provides clear semantics and maintains the distinction between errors and exits (matching Erlang/OTP semantics)
  • This approach avoids any risk of breaking existing error/1 and error/2 functionality
  • It's a minimal, focused addition to the error hierarchy

Concerns about this approach:

  • It adds a new file to the codebase (exit_error.mjs) which could be seen as expanding library infrastructure for a single function
  • An alternative might be to make HologramBoxedError more flexible to handle both cases, but that risks increasing complexity and coupling

Feedback on this design decision is welcome. If the maintainers prefer a different approach, it would be straightforward to refactor.

Test Results

✅ All quality gates passing:

  • 2324 JavaScript tests passing
  • 3600 Elixir tests passing
  • ESLint: ✅
  • Credo: ✅
  • Dialyzer: ✅
  • Code formatter: ✅
  • Sobelow (security): ✅
  • Hex audit: ✅

Scope Compliance

This PR follows all contribution guidelines:

  • ✅ One function per PR (only :erlang.exit/1)
  • ✅ Branch from dev (not master)
  • ✅ Follows existing patterns (mirrors error/1 and error/2)
  • ✅ Proper boxed type handling
  • ✅ No parameter mutations
  • ✅ Includes Start/End comments and Deps comment
  • ✅ Comprehensive test coverage (JavaScript and Elixir)
  • ✅ No unrelated changes

Implementation Notes

  • The function accepts any boxed value as the reason, matching Erlang semantics
  • Uses the same simple, focused pattern as error/1 and error/2
  • Properly integrated into the Erlang module in alphabetical order
  • No changes to CallGraph needed (no dependencies on other functions)

Note: This pull request was implemented using GitHub Copilot. Feedback on code quality, design decisions, and approach is welcome and appreciated.

@bartblast
Copy link
Owner

Hey @mward-sudo, thanks for the contribution!
I'll need to hold off on this for now. :erlang.exit/1 requires error handling infrastructure in the client runtime first, which isn't built yet. See "Client Error Handling" in the Hologram roadmap. I also don't yet know what the final implementation will look like once that foundation is in place.
Appreciate the effort though!

@mward-sudo
Copy link
Contributor Author

Noted. I'll look for some other things to implement and come back to this when the project is ready for it.

@mward-sudo mward-sudo marked this pull request as draft January 3, 2026 18:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Port :erlang.exit/1 to JS

2 participants