From 863c4207cc2adbbcbfa539fbfb4765c135801e77 Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Mon, 25 Mar 2024 03:36:32 +0100 Subject: feat(tvix/eval): contextful JSON operations `toJSON` transform a Nix structure into a JSON string. For each context in that Nix structure, the JSON string must possess it. Thus, it is necessary to take the union of all contexts and attach it to the final structure. Unfortunately, the return type of `into_json` is a serde's JSON object, not a string. Therefore, it is not possible to reuse `NixString` machinery. Context tests are reinforced as Nix does not test those behaviors. Fixes b/393. Change-Id: I5afdbc4e18dd70469192c1aa657d1049ba330149 Signed-off-by: Ryan Lahfa Reviewed-on: https://cl.tvl.fyi/c/depot/+/11266 Reviewed-by: flokli Tested-by: BuildkiteCI --- tvix/glue/src/builtins/derivation.rs | 7 +++---- .../tvix_tests/eval-okay-context-introspection.exp | 2 +- .../tvix_tests/eval-okay-context-introspection.nix | 10 ++++++++++ .../tvix_tests/eval-okay-context-propagation.exp | 2 +- .../tvix_tests/eval-okay-context-propagation.nix | 23 ++++++++++++++++++++++ 5 files changed, 38 insertions(+), 6 deletions(-) (limited to 'tvix/glue') diff --git a/tvix/glue/src/builtins/derivation.rs b/tvix/glue/src/builtins/derivation.rs index 078cb0e1ffd1..1a8d18943ebe 100644 --- a/tvix/glue/src/builtins/derivation.rs +++ b/tvix/glue/src/builtins/derivation.rs @@ -372,14 +372,13 @@ pub(crate) mod derivation_builtins { return Ok(val); } - // TODO(raitobezarius): context for json values? - // input_context.mimic(&val); - - let val_json = match val.into_json(&co).await? { + let (val_json, mut context) = match val.into_contextful_json(&co).await? { Ok(v) => v, Err(cek) => return Ok(Value::from(cek)), }; + input_context = input_context.join(&mut context); + // No need to check for dups, we only iterate over every attribute name once structured_attrs.insert(arg_name.to_owned(), val_json); } else { diff --git a/tvix/glue/src/tests/tvix_tests/eval-okay-context-introspection.exp b/tvix/glue/src/tests/tvix_tests/eval-okay-context-introspection.exp index 3f8905e9bd0d..a136b0035e0a 100644 --- a/tvix/glue/src/tests/tvix_tests/eval-okay-context-introspection.exp +++ b/tvix/glue/src/tests/tvix_tests/eval-okay-context-introspection.exp @@ -1 +1 @@ -[ true true true true true true true true true true true ] +[ true true true true true true true true true true true true true ] diff --git a/tvix/glue/src/tests/tvix_tests/eval-okay-context-introspection.nix b/tvix/glue/src/tests/tvix_tests/eval-okay-context-introspection.nix index 1b645b1a2607..ecd8ab0073d0 100644 --- a/tvix/glue/src/tests/tvix_tests/eval-okay-context-introspection.nix +++ b/tvix/glue/src/tests/tvix_tests/eval-okay-context-introspection.nix @@ -41,6 +41,13 @@ let reconstructed-path = appendContextFrom combo-path (builtins.unsafeDiscardStringContext combo-path); + an-str = { + a = "${drv}"; + }; + an-list = { + b = [ drv ]; + }; + # Eta rule for strings with context. etaRule = str: str == appendContextFrom @@ -70,4 +77,7 @@ in (etaRule "foo") (etaRule drv.drvPath) (etaRule drv.foo.outPath) + # `toJSON` tests + (builtins.hasContext (builtins.toJSON an-str)) + (builtins.hasContext (builtins.toJSON an-list)) ] diff --git a/tvix/glue/src/tests/tvix_tests/eval-okay-context-propagation.exp b/tvix/glue/src/tests/tvix_tests/eval-okay-context-propagation.exp index 8bb828e36a42..ff56f6ca18e7 100644 --- a/tvix/glue/src/tests/tvix_tests/eval-okay-context-propagation.exp +++ b/tvix/glue/src/tests/tvix_tests/eval-okay-context-propagation.exp @@ -1 +1 @@ -[ true true true true true true true true true true true true true true true true true true true true true true true true true true true true ] +[ true true true true true true true true true true true true true true true true true true true true true true true true true true true true true true true true true true ] diff --git a/tvix/glue/src/tests/tvix_tests/eval-okay-context-propagation.nix b/tvix/glue/src/tests/tvix_tests/eval-okay-context-propagation.nix index 918061b8b861..41e7f207b9e8 100644 --- a/tvix/glue/src/tests/tvix_tests/eval-okay-context-propagation.nix +++ b/tvix/glue/src/tests/tvix_tests/eval-okay-context-propagation.nix @@ -93,4 +93,27 @@ in (preserveContext other-drv (builtins.concatStringsSep "${other-drv}" [ "abc" "def" ])) # `attrNames` will never ever produce context. (preserveContext "abc" (toString (builtins.attrNames { a = { }; b = { }; c = { }; }))) + # `toJSON` preserves context of its inputs. + (preserveContexts [ drv other-drv ] (builtins.toJSON { + a = [ drv ]; + b = [ other-drv ]; + })) + (preserveContexts [ drv other-drv ] (builtins.toJSON { + a.deep = [ drv ]; + b = [ other-drv ]; + })) + (preserveContexts [ drv other-drv ] (builtins.toJSON { + a = "${drv}"; + b = [ other-drv ]; + })) + (preserveContexts [ drv other-drv ] (builtins.toJSON { + a.deep = "${drv}"; + b = [ other-drv ]; + })) + (preserveContexts [ drv other-drv ] (builtins.toJSON { + a = "${drv} ${other-drv}"; + })) + (preserveContexts [ drv other-drv ] (builtins.toJSON { + a.b.c.d.e.f = "${drv} ${other-drv}"; + })) ] -- cgit 1.4.1