-module(sandbox). -export([eval_pure/2, eval_pure/3]). %% Sandboxed evaluation of an Erlang fun. %% %% eval_pure/2(Fun, Arg) -> {ok, Result} | {error, Reason} %% eval_pure/3(Fun, Arg1, Arg2) -> {ok, Result} | {error, Reason} %% %% The 3-arity variant matches the (Activity, State) -> NewState %% shape of projection folds. The projection scheduler can wrap %% every fold call in `sandbox:eval_pure(Fun, Act, State)` to %% ensure a misbehaving fold body can't crash the projection %% gen_server. %% %% v1 sandboxing is just the try/catch envelope: no gas budget, %% no IO denial, no environment stripping. Real sandboxing lands %% with SX-source eval (the fold body would then be an SX form %% evaluated under the spec/harness platform). The API shape is %% stable — callers don't need to change when that arrives. %% Port note: this Erlang implementation catches by explicit %% class names (throw, error, exit) rather than the open %% `Class:Reason` pattern. The wrappers below enumerate the three. eval_pure(Fun, Arg) -> try Fun(Arg) of Result -> {ok, Result} catch throw:Reason -> {error, {throw, Reason}}; error:Reason -> {error, {error, Reason}}; exit:Reason -> {error, {exit, Reason}} end. eval_pure(Fun, Arg1, Arg2) -> try Fun(Arg1, Arg2) of Result -> {ok, Result} catch throw:Reason -> {error, {throw, Reason}}; error:Reason -> {error, {error, Reason}}; exit:Reason -> {error, {exit, Reason}} end.