mirror of
https://github.com/nushell/nushell.git
synced 2025-08-16 09:58:27 +02:00
reset argument/redirection state after eval_call
errors (#15400)
Closes #15395 # User-Facing Changes Certain errors no longer leave the argument stack in an unexpected state: ```diff let x: any = 1; try { $x | get path } catch { print caught } -$.path # extra `print` argument from the failed `get` call caught ``` # Description If `eval_call` fails in `check_input_types` or `gather_arguments`, the cleanup code is still executed.
This commit is contained in:
@ -82,6 +82,14 @@ fn catch_block_can_use_error_object() {
|
|||||||
assert_eq!(output.out, "Division by zero.")
|
assert_eq!(output.out, "Division by zero.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn catch_input_type_mismatch_and_rethrow() {
|
||||||
|
let actual = nu!(
|
||||||
|
"let x: any = 1; try { $x | get 1 } catch {|err| error make { msg: ($err | get msg) } }"
|
||||||
|
);
|
||||||
|
assert!(actual.err.contains("Input type not supported"));
|
||||||
|
}
|
||||||
|
|
||||||
// This test is disabled on Windows because they cause a stack overflow in CI (but not locally!).
|
// This test is disabled on Windows because they cause a stack overflow in CI (but not locally!).
|
||||||
// For reasons we don't understand, the Windows CI runners are prone to stack overflow.
|
// For reasons we don't understand, the Windows CI runners are prone to stack overflow.
|
||||||
// TODO: investigate so we can enable on Windows
|
// TODO: investigate so we can enable on Windows
|
||||||
|
@ -1026,8 +1026,7 @@ fn eval_call<D: DebugContext>(
|
|||||||
// Set up redirect modes
|
// Set up redirect modes
|
||||||
let mut caller_stack = caller_stack.push_redirection(redirect_out.take(), redirect_err.take());
|
let mut caller_stack = caller_stack.push_redirection(redirect_out.take(), redirect_err.take());
|
||||||
|
|
||||||
let result;
|
let result = (|| {
|
||||||
|
|
||||||
if let Some(block_id) = decl.block_id() {
|
if let Some(block_id) = decl.block_id() {
|
||||||
// If the decl is a custom command
|
// If the decl is a custom command
|
||||||
let block = engine_state.get_block(block_id);
|
let block = engine_state.get_block(block_id);
|
||||||
@ -1052,15 +1051,17 @@ fn eval_call<D: DebugContext>(
|
|||||||
// recoverable in Rust.
|
// recoverable in Rust.
|
||||||
callee_stack.recursion_count += 1;
|
callee_stack.recursion_count += 1;
|
||||||
|
|
||||||
result = eval_block_with_early_return::<D>(engine_state, &mut callee_stack, block, input);
|
let result =
|
||||||
|
eval_block_with_early_return::<D>(engine_state, &mut callee_stack, block, input);
|
||||||
|
|
||||||
// Move environment variables back into the caller stack scope if requested to do so
|
// Move environment variables back into the caller stack scope if requested to do so
|
||||||
if block.redirect_env {
|
if block.redirect_env {
|
||||||
redirect_env(engine_state, &mut caller_stack, &callee_stack);
|
redirect_env(engine_state, &mut caller_stack, &callee_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result
|
||||||
} else {
|
} else {
|
||||||
check_input_types(&input, &decl.signature(), head)?;
|
check_input_types(&input, &decl.signature(), head)?;
|
||||||
|
|
||||||
// FIXME: precalculate this and save it somewhere
|
// FIXME: precalculate this and save it somewhere
|
||||||
let span = Span::merge_many(
|
let span = Span::merge_many(
|
||||||
std::iter::once(head).chain(
|
std::iter::once(head).chain(
|
||||||
@ -1081,8 +1082,9 @@ fn eval_call<D: DebugContext>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Run the call
|
// Run the call
|
||||||
result = decl.run(engine_state, &mut caller_stack, &(&call).into(), input);
|
decl.run(engine_state, &mut caller_stack, &(&call).into(), input)
|
||||||
};
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
drop(caller_stack);
|
drop(caller_stack);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user