jsonnet
jsonnet copied to clipboard
Different behavior of hidden status inheritance between Jsonnet and Go-Jsonnet
Summary
I've been evaluating switching to Go-Jsonnet for our tooling and stumbled across a difference in how hidden status inheritance (https://jsonnet.org/ref/spec.html#hidden_inheritance) is implemented in Jsonnet and Go-Jsonnet.
Here's an example Jsonnet script which demonstrates the difference:
// `makeMergeable` is taken from our tooling. We use this extensively to make user inputs loaded from YAML mergeable
local makeMergeable(o) = {
[key]+: makeMergeable(o[key])
for key in std.objectFields(o)
if std.isObject(o[key])
} + {
[key]+: o[key]
for key in std.objectFields(o)
if std.isArray(o[key])
} + {
[key]: o[key]
for key in std.objectFields(o)
if !std.isObject(o[key]) && !std.isArray(o[key])
};
local base = { field:: 'data' };
{
regular: base { field: 'other' }, // hidden status of `field` is inherited in both implementations
makeMergeable: base + makeMergeable({
field: 'other',
}), // hidden status of `field` is inherited through the object comprehension in go-jsonnet, but the hidden status of the field is lost in jsonnet
}
From what I can tell, the go-jsonnet implementation implements the specification correctly.
Example script evaluation and output
I've wrapped the example in Python (because that's what I had readily available) to run both implementations side-by-side:
import _jsonnet
import _gojsonnet
prog = """
// `makeMergeable` is taken from our tooling. We use this extensively to make user inputs mergeable
local makeMergeable(o) = {
[key]+: makeMergeable(o[key])
for key in std.objectFields(o)
if std.isObject(o[key])
} + {
[key]+: o[key]
for key in std.objectFields(o)
if std.isArray(o[key])
} + {
[key]: o[key]
for key in std.objectFields(o)
if !std.isObject(o[key]) && !std.isArray(o[key])
};
local base = { field:: 'data' };
{
regular: base { field: 'other' }, // hidden status of `field` is inherited in both implementations
makeMergeable: base + makeMergeable({
field: 'other',
}), // hidden status of `field` is inherited through the object comprehension in go-jsonnet, but the hidden status of the field is lost in jsonnet
}
"""
print("Jsonnet:\n" + _jsonnet.evaluate_snippet("test.jsonnet", prog))
print("Go-Jsonnet:\n" + _gojsonnet.evaluate_snippet("test.jsonnet", prog))
This gives the following in a virtualenv (setup with python3 -m venv venv && source venv/bin/activate && pip install jsonnet gojsonnet):
(venv) simon@phoenix:~/tmp/jsonnet-issue $ pip list
Package Version
---------- -------
gojsonnet 0.20.0
jsonnet 0.20.0
pip 22.0.2
setuptools 59.6.0
(venv) simon@phoenix:~/tmp/jsonnet-issue $ python test.py
Jsonnet:
{
"makeMergeable": {
"field": "other"
},
"regular": { }
}
Go-Jsonnet:
{
"makeMergeable": { },
"regular": { }
}