jsonnet = {
const { evaluate_snippet: __evaluate } = await LOAD_NATIVE_LIBRARY();
return Object.defineProperties({}, {
__evaluate: {
value: __evaluate,
},
_evaluate: {
value: _evaluate,
},
evaluate: {
enumerable: true,
value: evaluate,
},
});
async function evaluate({
filename,
code,
files={},
extStrs={},
extCodes={},
tlaStrs={},
tlaCodes={},
nativeCallbacks={},
maxIterations=1024,
...extra
}) {
const UNIQUE_SEPARATOR = ':--UNIQUE_SEPARATOR--:';
extStrs = { ...extStrs, '__STD_UNIQUE_SEPARATOR': UNIQUE_SEPARATOR };
code = `\
local __std = std + {
local std = self,
_unique_separator:: std.extVar('__STD_UNIQUE_SEPARATOR'),
_unset:: 'd209d4c8-2672-4c03-93e5-d084245597a9',
__native(name, args)::
local each(x) = std.toString(x);
local parts = ['', name] + args + [''];
local key = std.join(std._unique_separator, std.map(each, parts));
std.extVar(key),
_native(name, a, b, c, d, e, f)::
if false then false
else if a == std._unset then std.__native(name, [])
else if b == std._unset then std.__native(name, [a])
else if c == std._unset then std.__native(name, [a, b])
else if d == std._unset then std.__native(name, [a, b, c])
else if e == std._unset then std.__native(name, [a, b, c, d])
else if f == std._unset then std.__native(name, [a, b, c, d, e])
else std.__native(name, [a, b, c, d, e, f]),
native(name)::
function(a=std._unset, b=std._unset, c=std._unset, d=std._unset, e=std._unset, f=std._unset)
std._native(name, a, b, c, d, e, f),
dispatch(object, prefix)::
function(a=std._unset, b=std._unset, c=std._unset, d=std._unset, e=std._unset, f=std._unset)
if false then false
else if a == std._unset then object[prefix + '0']()
else if b == std._unset then object[prefix + '1'](a)
else if c == std._unset then object[prefix + '2'](a, b)
else if d == std._unset then object[prefix + '3'](a, b, c)
else if e == std._unset then object[prefix + '4'](a, b, c, d)
else if f == std._unset then object[prefix + '5'](a, b, c, d, e)
else object[prefix + '6'](a, b, c, d, e, f),
};
local std = __std;
${code}`;
if (Object.keys(extra).length) throw `Error: jsonnet.evaluate: Unexpected options: ${Object.keys(extra)}`;
let i, n;
for (i=0, n=maxIterations; i<n; ++i) {
try {
const promise = _evaluate({
filename,
code,
files,
extStrs,
extCodes,
tlaStrs,
tlaCodes,
});
let result = await promise;
try {
result = JSON.parse(result);
} catch (e) {}
return result;
} catch (e) {
const error = `${e}`;
let lo = error.indexOf(UNIQUE_SEPARATOR);
if (lo === -1) {
throw e;
}
let hi = error.lastIndexOf(UNIQUE_SEPARATOR);
hi += UNIQUE_SEPARATOR.length;
const key = error.substring(lo, hi);
const parts = key.split(UNIQUE_SEPARATOR);
parts.shift(); // remove beginning
parts.pop(); // remove end
const [name, ...args] = parts;
const callback = nativeCallbacks[name];
if (callback === undefined) {
throw `Error: jsonnet.evaluate: callback "${name}" does not exist`;
}
const promise = Promise.resolve(callback(...args));
const result = await promise;
extCodes = { ...extCodes, [key]: JSON.stringify(result) };
// console.log({ error, key });
}
await new Promise((resolve) => setTimeout(resolve, 0));
}
throw `Error: jsonnet.evaluate: max recursive iterations exceeded: ${i}`;
}
async function _evaluate({
filename,
code,
files={},
extStrs={},
extCodes={},
tlaStrs={},
tlaCodes={},
...extra
}) {
if (Object.keys(extra).length) throw `Error: jsonnet._evaluate: Unexpected options: ${Object.keys(extra)}`;
const result = await __evaluate(filename, code, files, extStrs, extCodes, tlaStrs, tlaCodes);
// return { result };
// if (result.startsWith('Error: ')) throw result;
return result;
}
async function LOAD_NATIVE_LIBRARY(identifier='_jsonnet') {
if (window[identifier] !== undefined) {
return window[identifier];
}
const before = new Set();
for (const key of Object.keys(window)) {
before.add(key);
}
const Go = await require('https://jsonnet.org/js/wasm_exec.js').catch(() => {
const go = window.Go;
delete window.Go;
return go;
});
const go = new Go();
const request = fetch("https://jsonnet.org/js/libjsonnet.wasm");
const response = await WebAssembly.instantiateStreaming(request, go.importObject);
go.run(response.instance);
const jsonnet = {};
for (let key of Object.keys(window)) {
if (before.has(key)) continue;
if (!key.startsWith('jsonnet_')) continue;
const value = window[key];
delete window[key];
key = key.substring('jsonnet_'.length);
jsonnet[key] = value;
}
window[identifier] = jsonnet;
return jsonnet;
}
}