Skip to content

Commit

Permalink
merge: #3441
Browse files Browse the repository at this point in the history
3441: fix(dal): restore old engine behavior when preparing function arguments r=zacharyhamm a=zacharyhamm

All prepared function arguments for a prototype function are gathered as a mapping between function argument names and an *array* of values. In the old engine, we always transformed that array of values to a single value if the array was len() == 1. The new engine func binding preparation special-cased input sockets function arguments to always send an array, since this means that functions take take input socket values as an input would not require special logic for handling the scalar case and the array case (e.g., the si:normalizeToArray function). However, our components are not built with this change in mind, and the new behavior breaks some components slightly (for example EC2 Instance sets the user data prop from the input socket with identity, so what we write to the string prop turns into an array value).

Co-authored-by: Zachary Hamm <[email protected]>
  • Loading branch information
si-bors-ng[bot] and zacharyhamm authored Mar 13, 2024
2 parents 93b5058 + d9ad704 commit 3511c15
Showing 1 changed file with 20 additions and 23 deletions.
43 changes: 20 additions & 23 deletions lib/dal/src/attribute/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,33 +568,30 @@ impl AttributeValue {
}
}

let prepared_func_binding_args = if let ValueIsFor::InputSocket(_) = &value_is_for {
// If our destination is an input socket, we always want to provide an array of
// the values so functions don't have to distinguish between a single value that is an
// array, or an array of values (for example if an input socket has multiple
// connections)
serde_json::to_value(func_binding_args)?
} else {
// The value map above could possibly have multiple values per func argument name if
// there are We need to transform these vecs to a serde_json array before sending them
// to the function executor. We also want to send a single value if there is only a
// single input, since that is the typical case and what is expected by most attribute
// functions.
let mut prepared_func_binding_args = HashMap::new();
for (arg_name, values) in func_binding_args {
if values.is_empty() {
// The value map above could possibly have multiple values per func
// argument name if there are multiple inputs (for example, more than
// one connection to an input socket). We need to transform these vecs
// to a serde_json array before sending them to the function executor.
// We also want to send a single value if there is only a single input,
// since that is the typical case and what is expected by most attribute
// functions.
let mut args_map = HashMap::new();
for (arg_name, values) in func_binding_args {
match values.len() {
1 => {
args_map.insert(arg_name, values[0].to_owned());
}
2.. => {
args_map.insert(arg_name, serde_json::to_value(values)?);
}
_ => {
return Err(
AttributeValueError::EmptyAttributePrototypeArgumentsForGroup(arg_name),
);
} else if values.len() == 1 {
prepared_func_binding_args.insert(arg_name, values[0].to_owned());
} else {
let vec_value = serde_json::to_value(values)?;
prepared_func_binding_args.insert(arg_name, vec_value);
)
}
}
serde_json::to_value(prepared_func_binding_args)?
};
}
let prepared_func_binding_args = serde_json::to_value(args_map)?;

// We need the associated [`ComponentId`] for this function--this is how we resolve and
// prepare before functions
Expand Down

0 comments on commit 3511c15

Please sign in to comment.