fix(tvix/eval): handle toJSON on attribute sets with outPath

These are serialised as the serialisation of the value of that field.

Change-Id: Ida51708b1f43ce09b0ec835f4e265918aa31dd09
Reviewed-on: https://cl.tvl.fyi/c/depot/+/8205
Reviewed-by: raitobezarius <tvl@lahfa.xyz>
Tested-by: BuildkiteCI
This commit is contained in:
Vincent Ambo 2023-03-04 00:06:00 +03:00 committed by tazjin
parent 7d339d2762
commit dfd0066de5
5 changed files with 38 additions and 6 deletions

View file

@ -359,13 +359,30 @@ mod pure_builtins {
#[builtin("toJSON")]
async fn builtin_to_json(co: GenCo, val: Value) -> Result<Value, ErrorKind> {
if let Value::Attrs(attrs) = &val {
// Attribute sets with a callable `__toString` attribute
// serialise to the string-coerced version of the result of
// calling that.
if let Some(s) = attrs.try_to_string(&co, CoercionKind::Weak).await {
return Ok(Value::String(serde_json::to_string(&s)?.into()));
let mut val = val; // shadow mutably, not supported by macro
loop {
if let Value::Attrs(attrs) = &val {
// Attribute sets with a callable `__toString` attribute
// serialise to the string-coerced version of the result of
// calling that.
if let Some(s) = attrs.try_to_string(&co, CoercionKind::Weak).await {
return Ok(Value::String(serde_json::to_string(&s)?.into()));
}
// Attribute sets with an `outPath` attribute
// serialise to a JSON serialisation of that inner
// value (regardless of what it is!).
if let Some(out_path) = attrs.select("outPath") {
val = out_path.clone();
continue;
}
// Attribute set should be serialised normally (by
// traversing it and serialising keys/values).
break;
}
break;
}
// All thunks need to be evaluated before serialising, as the

View file

@ -0,0 +1 @@
"{\"a\":40,\"b\":2}"

View file

@ -0,0 +1,8 @@
# Attribute sets with an `outPath` can contain _any_ serialisable
# value in that field.
builtins.toJSON {
outPath = {
a = 40;
b = 2;
};
}

View file

@ -0,0 +1 @@
"\"/nix/store/jzka5ndnygkkfjfvpqwjipqp75lhz138-emacs-28.2\""

View file

@ -0,0 +1,5 @@
# Attribute sets with an `outPath` have that outPath itself serialised
# to string.
builtins.toJSON {
outPath = "/nix/store/jzka5ndnygkkfjfvpqwjipqp75lhz138-emacs-28.2";
}