Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
19c946c
Add QuickJS bytecode decoder (Phase 0.2-0.3)
dannote Apr 14, 2026
9e0889d
Add BEAM VM instruction decoder and interpreter (Phase 1)
dannote Apr 15, 2026
5ba98f7
Fix interpreter: args separate from locals, post_inc stack order, lab…
dannote Apr 15, 2026
63bdb63
Complete Phase 1: objects, closures, named functions, 69/69 tests pas…
dannote Apr 15, 2026
a7bebcd
Add JS built-in runtime (Phase 2): arrays, strings, objects, Math, JS…
dannote Apr 15, 2026
7c1c574
Replace Jason with built-in :json (OTP 26+)
dannote Apr 15, 2026
1d0088a
Add beam mode eval API and fix critical interpreter bugs
dannote Apr 15, 2026
6bc98ce
Fix array/object mutation, tail call builtins, strict equality
dannote Apr 15, 2026
1169ee2
Split Runtime into domain modules
dannote Apr 15, 2026
61aa63b
Review fixes: deduplicate norm_idx, explicit try/rescue, snake_case r…
dannote Apr 15, 2026
a79227d
Implement try/catch and computed property assignment (90/91 compat)
dannote Apr 15, 2026
9a5b594
Implement mutable closures via shared cells (91/91 compat)
dannote Apr 15, 2026
0a391e3
Address review: dead code, captured locals safety, inc/dec/add_loc cells
dannote Apr 15, 2026
8c6c5cd
Add beam mode compat test suite (143/152 pass, 9 pending)
dannote Apr 15, 2026
784decc
Fix stack order in for_of_next/for_in_next, add constructor this-binding
dannote Apr 16, 2026
d674aca
Add WPT-style built-in conformance tests (186 tests, all pass)
dannote Apr 16, 2026
289e0aa
Add WPT language semantics tests (54/59 pass), fix this-binding and m…
dannote Apr 16, 2026
cbbdf10
Replace fake WPT tests with dual-mode NIF/BEAM comparison (252 tests)
dannote Apr 16, 2026
e97aa24
Expand dual-mode test to 278 expressions
dannote Apr 16, 2026
5c55021
Fix multi-byte UTF-8 string handling in bytecode decoder
dannote Apr 16, 2026
ba46b69
Fix all compiler warnings in beam_vm modules
dannote Apr 16, 2026
06aaa82
Pass gas through to inner calls instead of halving
dannote Apr 16, 2026
06cf608
Fix this-binding, get_loc0_loc1 stack order, remove duplicate push_this
dannote Apr 16, 2026
afec016
Fix rest params, string indexing, new Array(), call_constructor name …
dannote Apr 16, 2026
adc3afe
Fix computed property keys, charAt bounds, Array.lastIndexOf, define_…
dannote Apr 16, 2026
0afae43
Fix negative zero, Infinity arithmetic, String.fromCharCode, more edg…
dannote Apr 16, 2026
f656087
Add Map/Set, method shorthand, Object.defineProperty, put_loc8 expansion
dannote Apr 16, 2026
339eb5c
Fix classes, Map/Set, arguments object, define_class stack order
dannote Apr 16, 2026
1157a19
Address review: remove duplicate opcodes, fix prototype chain, class …
dannote Apr 16, 2026
5df5c4f
Add class inheritance scaffolding: get_super, define_class parent chain
dannote Apr 16, 2026
143b7c3
Fix call_constructor stack layout for super() calls
dannote Apr 16, 2026
36cf298
Fix call_constructor fallback and debug cleanup
dannote Apr 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
845 changes: 845 additions & 0 deletions ROADMAP.md

Large diffs are not rendered by default.

42 changes: 41 additions & 1 deletion lib/quickbeam.ex
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,48 @@ defmodule QuickBEAM do
"""
@spec eval(runtime(), String.t(), keyword()) :: js_result()
def eval(runtime, code, opts \\ []) do
QuickBEAM.Runtime.eval(runtime, code, opts)
if Keyword.get(opts, :mode) == :beam do
eval_beam(runtime, code, opts)
else
QuickBEAM.Runtime.eval(runtime, code, opts)
end
end

defp eval_beam(runtime, code, _opts) do
alias QuickBEAM.BeamVM.{Bytecode, Interpreter}
case QuickBEAM.Runtime.compile(runtime, code) do
{:ok, bc} ->
case Bytecode.decode(bc) do
{:ok, parsed} ->
result = Interpreter.eval(parsed.value, [], %{gas: 1_000_000_000}, parsed.atoms)
convert_beam_result(result)
{:error, _} = err -> err
end
{:error, _} = err -> err
end
end

defp convert_beam_result({:error, {:js_throw, {:obj, _ref} = obj}}) do
# Convert thrown Error objects to maps
val = convert_beam_value(obj)
{:error, val}
end
defp convert_beam_result({:error, {:js_throw, val}}), do: {:error, convert_beam_value(val)}
defp convert_beam_result({:ok, {:obj, ref}}) do
{:ok, convert_beam_value({:obj, ref})}
end
defp convert_beam_result({:ok, val}), do: {:ok, convert_beam_value(val)}
defp convert_beam_result({:error, _} = err), do: err

defp convert_beam_value(:undefined), do: nil
defp convert_beam_value({:obj, ref}) do
case Process.get({:qb_obj, ref}) do
nil -> nil
list when is_list(list) -> Enum.map(list, &convert_beam_value/1)
map when is_map(map) -> Map.new(map, fn {k, v} -> {k, convert_beam_value(v)} end)
end
end
defp convert_beam_value(v), do: v

@doc """
Call a global JavaScript function by name.
Expand Down
Loading
Loading