fix(tvix/eval): implement cppnix JSON-serialisation semantics
This drops the usage of serde::Serialize, as the trait can not be used to implement the correct semantics (function colouring!). Instead, a manual JSON serialisation function is written which correctly handles toString, outPath and other similar weirdnesses. Unexpectedly, the eval-okay-tojson test from the C++ Nix test suite now passes, too. This fixes an issue where serialising data structures containing derivations to JSON would fail. Change-Id: I5c39e3d8356ee93a07eda481410f88610f6dd9f8 Reviewed-on: https://cl.tvl.fyi/c/depot/+/8209 Reviewed-by: raitobezarius <tvl@lahfa.xyz> Tested-by: BuildkiteCI
This commit is contained in:
parent
1e37f8b52e
commit
939cebd0f1
12 changed files with 138 additions and 70 deletions
|
|
@ -359,36 +359,8 @@ mod pure_builtins {
|
|||
|
||||
#[builtin("toJSON")]
|
||||
async fn builtin_to_json(co: GenCo, val: Value) -> Result<Value, ErrorKind> {
|
||||
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
|
||||
// data structure is fully traversed by the Serializer.
|
||||
let val = generators::request_deep_force(&co, val, SharedThunkSet::default()).await;
|
||||
let json_str = serde_json::to_string(&val)?;
|
||||
let json_value = val.to_json(&co).await?;
|
||||
let json_str = serde_json::to_string(&json_value)?;
|
||||
Ok(json_str.into())
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue