From d1e2f8e66f2e9565c23cd24f7e6d657a996ba6c2 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Wed, 20 Mar 2024 19:24:07 +0000 Subject: [PATCH] fix: field in super should not be interpreted with standalone-super concept. Jsonnet spec defines special behavior for `super.field` and `field in super` expressions, while in jrsonnet it is implemented by standalone-super concept, with optimizations in case of `super.field`. However, standalone-super is conflicting with `field in super` behavior, so special handling is needed for this expression. --- --- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs +++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs @@ -3,8 +3,8 @@ use jrsonnet_gcmodule::{Cc, Trace}; use jrsonnet_interner::IStr; use jrsonnet_parser::{ - ArgsDesc, AssertStmt, BindSpec, CompSpec, Expr, FieldMember, FieldName, ForSpecData, - IfSpecData, LiteralType, LocExpr, Member, ObjBody, ParamsDesc, + ArgsDesc, AssertStmt, BinaryOpType, BindSpec, CompSpec, Expr, FieldMember, FieldName, + ForSpecData, IfSpecData, LiteralType, LocExpr, Member, ObjBody, ParamsDesc, }; use jrsonnet_types::ValType; @@ -439,6 +439,21 @@ Parened(e) => evaluate(ctx, e)?, Str(v) => Val::string(v.clone()), Num(v) => Val::new_checked_num(*v)?, + // I have tried to remove special behavior from super by implementing standalone-super + // expresion, but looks like this case still needs special treatment. + // + // Note that other jsonnet implementations will fail on `if value in (super)` expression, + // because the standalone super literal is not supported, that is because in other + // implementations `in super` treated differently from in `smth_else`. + BinaryOp(field, BinaryOpType::In, e) + if matches!(&*e.0, Expr::Literal(LiteralType::Super)) => + { + let Some(super_obj) = ctx.super_obj() else { + return Ok(Val::Bool(false)); + }; + let field = evaluate(ctx.clone(), field)?; + Val::Bool(super_obj.has_field_ex(field.to_string()?, true)) + } BinaryOp(v1, o, v2) => evaluate_binary_op_special(ctx, v1, *o, v2)?, UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(ctx, v)?)?, Var(name) => State::push( --- /dev/null +++ b/tests/golden/issue153.jsonnet @@ -0,0 +1,9 @@ +local upper = { + 'bar': if 'baz' in super then super.baz else 'nope', +}; + +local obj = { + foo+: upper, +}; + +obj --- /dev/null +++ b/tests/golden/issue153.jsonnet.golden @@ -0,0 +1,5 @@ +{ + "foo": { + "bar": "nope" + } +} \ No newline at end of file -- gitstuff