fix(vm): return terse error value for ArgumentError at protected-call boundary#354
Merged
Merged
Conversation
… boundary `Lua.VM.ProtectedCall.error_value/1` had no clause for `Lua.VM.ArgumentError`, so it fell through to `Exception.message/1` — which calls `ErrorFormatter.format/3` and embeds ANSI escape codes plus the `at <source>:<line>:` header in the returned reason. PR #337 plugged this for the `:value`-bearing exceptions (`RuntimeError`, `TypeError`, `AssertionError`) but `ArgumentError` builds its message from individual fields and has no `:value` slot, so it was missed. Affected both `Lua.call_function/3` and `pcall`/`xpcall`: any stdlib bad-argument raise (e.g. `pairs("asdf")`) returned the rendered string instead of the bare §6.1 error value. Promote `ArgumentError.build_base/5` to a public `raw_message/1` and add a clause to `error_value/1` that returns it. Regression tests added for both protected-call boundaries. Fixes #342.
`Lua.VM.ProtectedCall` is `@moduledoc false`, so the autolink from `ArgumentError.raw_message/1`'s public doc tripped `mix docs --warnings-as-errors` on CI.
`Lua.call_function!/3` raises `Lua.RuntimeException` whose `:original`
field carries the underlying VM exception verbatim. That's the escape
hatch for Elixir callers who want to pattern-match on the structured
error (e.g. `%Lua.VM.ArgumentError{function_name: "pairs", arg_num: 1,
expected: "table", got: "string"}`) instead of parsing the terse §6.1
string that `call_function/3` returns.
The contract was already implemented (RuntimeException.exception/1 line
66 stores `original: error`) but wasn't pinned by a test, so a future
refactor that wrapped or stringified the underlying exception would have
silently regressed it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Lua.VM.ProtectedCall.error_value/1had no clause forLua.VM.ArgumentError, so it fell through toException.message/1— embedding ANSI codes and theat <source>:<line>:header in the reason returned byLua.call_function/3andpcall/xpcall. PR fix(vm): return terse Lua error value from call_function, not terminal render (#336) #337 only fixed the:value-bearing exceptions (RuntimeError,TypeError,AssertionError);ArgumentErrorbuilds its message from individual fields and has no:valueslot.ArgumentError.build_base/5to a publicraw_message/1, and add anArgumentErrorclause toerror_value/1that returns it.call_function/3andpcall), plus tests pinningcall_function!/3's structured-exception passthrough.Fixes #342.
Repro (before)
After
call_function/3returns the §6.1-faithful terse string (matchingpcall's contract):call_function!/3is the escape hatch for Elixir callers who want the structured exception — it raisesLua.RuntimeExceptionwhose:originalfield carries the underlying VM exception verbatim, so you can pattern-match on it:Test plan
mix test test/lua/call_function_error_value_test.exs(14 cases, +6: ArgumentError regression, ANSI-on variant, and 3 cases pinningcall_function!/3's.originalcontract forArgumentError/RuntimeError/TypeError)mix test test/lua/vm/pcall_error_value_test.exs(+2 cases, one per engine)mix test— full suite green (2256+ passed, 19 skipped)Lua.call_function/3expected to returnLua.RuntimeExceptioninstead of string with ANSI codes #342 returns terse one-line string with no ANSI / no header / no newlinesmix docs --warnings-as-errorscleanmix formatclean