difftreelog
refactor split libjsonnet code into modules
in: master
11 files changed
bindings/c/.gitignorediffbeforeafterbothno changes
bindings/js/index.jsdiffbeforeafterboth1const fs = require('fs');1const fs = require('fs');2const path = require('path');2const { WASI } = require('wasi');3const { WASI } = require('wasi');3const wasi = new WASI({4const wasi = new WASI({4 args: process.argv,5 args: process.argv,5 env: process.env,6 env: process.env,6 preopens: {},7 preopens: {},7});8});8const importObject = { wasi_snapshot_preview1: wasi.wasiImport };9910class JsonnetVM {10class JsonnetVM {11 constructor(wasm, vm) {11 constructor(wasm, vm) {12 this.wasm = wasm;12 this.wasm = wasm;13 this.vm = vm;13 this.vm = vm;14 this.wasm.exports.jrsonnet_set_trace_format(this.vm, 1);1516 this.setImportCallback((from, to) => {17 const resolved = path.resolve(from, to);18 return {19 value: fs.readFileSync(resolved).toString('utf-8'),20 foundHere: resolved,21 };22 })14 }23 }2425 /**26 * @param {(from: string, to: string) => {foundHere: string, value: string}} cb27 */28 setImportCallback(cb) {29 this.wasm.importCbs.set(this.vm, (base, rel, foundHere, success) => {30 const baseStr = this.wasm.readString(base);31 const relStr = this.wasm.readString(rel);32 try {33 const value = cb(baseStr, relStr);34 this.wasm.memorySlice32Len(foundHere, 1)[0] = this.allocateString(value.foundHere);35 this.wasm.memorySlice32Len(success, 1)[0] = 1;36 return this.allocateString(value.value);37 } catch (e) {38 this.wasm.memorySlice32Len(success, 1)[0] = 0;39 return this.allocateString(e.stack)40 }41 });42 this.wasm.exports.jrsonnet_apply_static_import_callback(43 this.vm,44 this.vm,45 );46 }154716 alloc(length) {48 alloc(length) {17 return this.wasm.exports.jsonnet_realloc(this.vm, 0, length);49 return this.wasm.exports.jsonnet_realloc(this.vm, 0, length);18 }50 }19 allocateString(string) {51 allocateString(string) {20 const byteLength = new TextEncoder().encode(string).length;52 const byteLength = new TextEncoder().encode(string).length;21 const addr = this.alloc(byteLength);53 const addr = this.alloc(byteLength + 1);22 this.wasm.writeString(addr, string);54 this.wasm.writeString(addr, string);23 return addr;55 return addr;24 }56 }36 const result = this.wasm.readString(resultAddr).trim();68 const result = this.wasm.readString(resultAddr).trim();37 this.dealloc(resultAddr);69 this.dealloc(resultAddr);38 if (resultCode[0] === 1) {70 if (resultCode[0] === 1) {39 const error = new Error(this.normalizeErrorString(result));71 const error = new Error(result);40 throw error;72 throw error;41 } else {73 } else {42 return result;74 return result;54 const result = this.wasm.readString(resultAddr);86 const result = this.wasm.readString(resultAddr);55 this.dealloc(resultAddr);87 this.dealloc(resultAddr);56 if (resultCode[0] === 1) {88 if (resultCode[0] === 1) {57 const error = new Error(this.normalizeErrorString(result));89 const error = new Error(result);58 throw error;90 throw error;59 } else {91 } else {60 return result;92 return result;61 }93 }62 }94 }9596 /**97 * Destroys vm, any future call to this object will fail, and all resources will be freed98 */63 normalizeErrorString(str) {99 destroy() {64 str = str.trim();100 this.wasm.exports.jsonnet_destroy(this.vm);65 const newLine = str.indexOf('\n');66 if (newLine === -1) return str;67 let message = str.slice(0, newLine);68 let trace = str.slice(newLine + 1).split('\n').map(s => s.split(' ---- ')).map(([p, v]) => ` at ${v} (${p})`).join('\n');101 this.wasm.importCbs.delete(this.vm);69 return `${message}\n${trace}`;70 }102 }71}103}7210473class JsonnetWASM {105class JsonnetWASM {74 constructor() { }106 constructor() {107 this.importCbs = new Map();108 }7510976 async init(buf) {110 async init(buf) {77 const wasm = await WebAssembly.compile(buf);111 const wasm = await WebAssembly.compile(buf);78 const instance = await WebAssembly.instantiate(wasm, importObject);112 const instance = await WebAssembly.instantiate(wasm, {113 wasi_snapshot_preview1: wasi.wasiImport,114 env: {115 _jrsonnet_static_import_callback: (ctx, base, rel, found_here, success) => {116 if (!this.importCbs.has(ctx)) {117 throw new Error(`Got unknown ctx callback: ${ctx}`);118 }119 return this.importCbs.get(ctx)(base, rel, found_here, success);120 }121 }122 });79 wasi.start(instance);123 wasi.start(instance);80 this.instance = instance;124 this.instance = instance;81 }125 }126 /**127 * @type Record<string, WebAssembly.ExportValue>128 */82 get exports() {129 get exports() {83 return this.instance.exports;130 return this.instance.exports;84 }131 }91 memorySliceLen(start, length) {138 memorySliceLen(start, length) {92 return new Uint8Array(this.memoryBuffer, start, length);139 return new Uint8Array(this.memoryBuffer, start, length);93 }140 }141 memorySlice32Len(start, length) {142 return new Uint32Array(this.memoryBuffer, start, length);143 }94 memorySlice(start, end) {144 memorySlice(start, end) {95 return new Uint8Array(this.memoryBuffer, start, start && end && (end - start));145 return new Uint8Array(this.memoryBuffer, start, start && end && (end - start));96 }146 }119(async () => {169(async () => {120 try {170 try {121 const jsonnet = new JsonnetWASM();171 const jsonnet = new JsonnetWASM();122 await jsonnet.init(fs.readFileSync(`${__dirname}/../../target/wasm32-wasi/release/jsonnet.wasi.wasm`));172 await jsonnet.init(fs.readFileSync(`${__dirname}/../../target/wasm32-wasi/release/jsonnet.wasm`));123 console.log(`Version = ${jsonnet.version()}`);173 console.log(`Version = ${jsonnet.version()}`);124174125 const vm = jsonnet.newVM();175 const vm = jsonnet.newVM();126 console.log(vm.evaluateSnippet('./snip.jsonnet', `176 console.log(vm.evaluateSnippet('./snip.jsonnet', `127 local a(b) = error "sad" + b;177 2+2128 local c() = a(2 + 2);129 c()130 `))178 `));131 console.log(vm.evaluateFile('./test.jsonnet'));179 console.log(vm.evaluateFile('./test.jsonnet'));132 } catch (e) {180 } catch (e) {133 console.log(e.stack);181 console.log(e.stack);bindings/jsonnet/Cargo.tomldiffbeforeafterboth9[dependencies]9[dependencies]10jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "1.0.0" }10jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "1.0.0" }11jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "1.0.0" }11jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "1.0.0" }12libc = "0.2.71"131214[lib]13[lib]15crate-type = ["cdylib"]14crate-type = ["cdylib"]bindings/jsonnet/src/interop.rsdiffbeforeafterbothno changes
bindings/jsonnet/src/lib.rsdiffbeforeafterboth1use jrsonnet_evaluator::{1#![feature(custom_inner_attributes)]2 create_error, create_error_result, Error, EvaluationState, ImportResolver, LazyBinding,23 LazyVal, ObjMember, ObjValue, Result, Val,3pub mod import;4};4pub mod interop;5pub mod val_extract;6pub mod val_make;7pub mod val_modify;8pub mod vars_tlas;95use jrsonnet_parser::Visibility;10use import::NativeImportResolver;6use libc::{c_char, c_double, c_int, c_uint};11use jrsonnet_evaluator::{EvaluationState, ManifestFormat, Val};7use std::{12use std::{8 alloc::Layout,13 alloc::Layout,9 any::Any,10 cell::RefCell,11 collections::HashMap,12 ffi::{CStr, CString},14 ffi::{CStr, CString},13 fs::File,15 os::raw::{c_char, c_double, c_int, c_uint},14 io::Read,15 path::PathBuf,16 path::PathBuf,16 rc::Rc,17 rc::Rc,17};18};181920/// WASM stub19#[no_mangle]21#[no_mangle]20#[cfg(target = "wasm32-wasi")]21pub extern "C" fn _start() {}22pub extern "C" fn _start() {}222323#[no_mangle]24#[no_mangle]24pub extern "C" fn jsonnet_version() -> &'static [u8; 8] {25pub extern "C" fn jsonnet_version() -> &'static [u8; 8] {25 b"v0.16.0\0"26 b"v0.16.0\0"26}27}2728#[derive(Default)]29struct NativeImportResolver {30 library_paths: RefCell<Vec<PathBuf>>,31}32impl NativeImportResolver {33 fn add_jpath(&self, path: PathBuf) {34 self.library_paths.borrow_mut().push(path);35 }36}37impl ImportResolver for NativeImportResolver {38 fn resolve_file(&self, from: &PathBuf, path: &PathBuf) -> Result<Rc<PathBuf>> {39 let mut new_path = from.clone();40 new_path.push(path);41 if new_path.exists() {42 Ok(Rc::new(new_path))43 } else {44 for library_path in self.library_paths.borrow().iter() {45 let mut cloned = library_path.clone();46 cloned.push(path);47 if cloned.exists() {48 return Ok(Rc::new(cloned));49 }50 }51 create_error_result(Error::ImportFileNotFound(from.clone(), path.clone()))52 }53 }54 fn load_file_contents(&self, id: &PathBuf) -> Result<Rc<str>> {55 let mut file =56 File::open(id).map_err(|_e| create_error(Error::ResolvedFileNotFound(id.clone())))?;57 let mut out = String::new();58 file.read_to_string(&mut out)59 .map_err(|_e| create_error(Error::ImportBadFileUtf8(id.clone())))?;60 Ok(out.into())61 }62 unsafe fn as_any(&self) -> &dyn Any {63 self64 }65}662867#[no_mangle]29#[no_mangle]68pub extern "C" fn jsonnet_make() -> *mut EvaluationState {30pub extern "C" fn jsonnet_make() -> *mut EvaluationState {90#[no_mangle]52#[no_mangle]91pub extern "C" fn jsonnet_gc_growth_trigger(_vm: &EvaluationState, _v: c_double) {}53pub extern "C" fn jsonnet_gc_growth_trigger(_vm: &EvaluationState, _v: c_double) {}925493// TODO94#[no_mangle]55#[no_mangle]95pub extern "C" fn jsonnet_string_output(_vm: &EvaluationState, _v: c_int) {56pub extern "C" fn jsonnet_string_output(vm: &EvaluationState, v: c_int) {96 todo!()97}9899#[no_mangle]100pub extern "C" fn jsonnet_json_extract_string(_vm: &EvaluationState, v: &Val) -> *mut c_char {101 match v.unwrap_if_lazy().unwrap() {102 Val::Str(s) => CString::new(&*s as &str).unwrap().into_raw(),103 _ => std::ptr::null_mut(),104 }105}106#[no_mangle]107pub extern "C" fn jsonnet_json_extract_number(108 _vm: &EvaluationState,109 v: &Val,110 out: &mut c_double,111) -> c_int {112 match v.unwrap_if_lazy().unwrap() {113 Val::Num(n) => {114 *out = n;115 1116 }117 _ => 0,118 }119}120#[no_mangle]121pub extern "C" fn jsonnet_json_extract_bool(_vm: &EvaluationState, v: &Val) -> c_int {122 match v.unwrap_if_lazy().unwrap() {123 Val::Bool(false) => 0,124 Val::Bool(true) => 1,125 _ => 2,126 }127}128#[no_mangle]129pub extern "C" fn jsonnet_json_extract_null(_vm: &EvaluationState, v: &Val) -> c_int {130 match v.unwrap_if_lazy().unwrap() {131 Val::Null => 1,132 _ => 0,133 }134}135136/// # Safety137///138/// This function is safe, if received v is a pointer to normal C string139#[no_mangle]140pub unsafe extern "C" fn jsonnet_json_make_string(141 _vm: &EvaluationState,142 v: *const c_char,143) -> *mut Val {144 let cstr = CStr::from_ptr(v);145 let str = cstr.to_str().unwrap();146 Box::into_raw(Box::new(Val::Str(str.into())))147}148149#[no_mangle]150pub extern "C" fn jsonnet_json_make_number(_vm: &EvaluationState, v: c_double) -> *mut Val {151 Box::into_raw(Box::new(Val::Num(v)))152}153154#[no_mangle]155pub extern "C" fn jsonnet_json_make_bool(_vm: &EvaluationState, v: c_int) -> *mut Val {156 assert!(v == 0 || v == 1);157 Box::into_raw(Box::new(Val::Bool(v == 1)))158}159160#[no_mangle]161pub extern "C" fn jsonnet_json_make_null(_vm: &EvaluationState) -> *mut Val {162 Box::into_raw(Box::new(Val::Null))163}164165#[no_mangle]166pub extern "C" fn jsonnet_json_make_array(_vm: &EvaluationState) -> *mut Val {167 Box::into_raw(Box::new(Val::Arr(Rc::new(Vec::new()))))168}169170#[no_mangle]171pub extern "C" fn jsonnet_json_array_append(_vm: &EvaluationState, arr: &mut Val, val: &Val) {172 match arr {173 Val::Arr(old) => {174 // TODO: Mutate array, instead of recreating them175 let mut new = Vec::new();176 new.extend(old.iter().cloned());177 new.push(val.clone());178 *arr = Val::Arr(Rc::new(new));179 }180 _ => panic!("should receive array"),181 }182}183184#[no_mangle]185pub extern "C" fn jsonnet_json_make_object(_vm: &EvaluationState) -> *mut Val {186 Box::into_raw(Box::new(Val::Obj(ObjValue::new_empty())))187}188189/// # Safety190///191/// This function is safe if passed name is ok192#[no_mangle]193pub unsafe extern "C" fn jsonnet_json_object_append(194 _vm: &EvaluationState,195 obj: &mut Val,196 name: *const c_char,197 val: &Val,198) {199 match obj {57 match v {58 1 => vm.set_manifest_format(ManifestFormat::None),200 Val::Obj(old) => {59 0 => vm.set_manifest_format(ManifestFormat::Json(4)),201 let mut new = HashMap::new();202 new.insert(203 CStr::from_ptr(name).to_str().unwrap().into(),204 ObjMember {205 add: false,206 visibility: Visibility::Normal,207 invoke: LazyBinding::Bound(LazyVal::new_resolved(val.clone())),208 location: None,209 },210 );211 let new_obj = ObjValue::new(Some(old.clone()), Rc::new(new));212 *obj = Val::Obj(new_obj);213 }214 _ => panic!("should receive array"),60 _ => panic!("incorrect output format"),215 }61 }216}62}21763247 Box::from_raw(v);93 Box::from_raw(v);248}94}24995250#[no_mangle]251pub extern "C" fn jsonnet_import_callback() {252 todo!()253}254#[no_mangle]96#[no_mangle]255pub extern "C" fn jsonnet_native_callback() {97pub extern "C" fn jsonnet_native_callback() {256 todo!()98 todo!()257}99}100258#[no_mangle]101#[no_mangle]259pub extern "C" fn jsonnet_ext_var() {102pub extern "C" fn jsonnet_max_trace(vm: &EvaluationState, v: c_uint) {260 todo!()261}262#[no_mangle]263pub extern "C" fn jsonnet_ext_code() {264 todo!()265}266#[no_mangle]267pub extern "C" fn jsonnet_tla_var() {268 todo!()269}270#[no_mangle]271pub extern "C" fn jsonnet_tla_code() {272 todo!()273}274#[no_mangle]275pub extern "C" fn jsonnet_max_trace() {276 todo!()277}278279/// # Safety280///281/// This function is safe, if received v is a pointer to normal C string282#[no_mangle]283pub unsafe extern "C" fn jsonnet_jpath_add(vm: &EvaluationState, v: *const c_char) {284 let cstr = CStr::from_ptr(v);285 let path = PathBuf::from(cstr.to_str().unwrap());286 let any_resolver = &vm.settings().import_resolver;103 vm.set_max_trace(v as usize)287 let resolver = any_resolver288 .as_any()289 .downcast_ref::<NativeImportResolver>()290 .unwrap();291 resolver.add_jpath(path);292}104}293105294/// # Safety106/// # Safety301 error: &mut c_int,113 error: &mut c_int,302) -> *const c_char {114) -> *const c_char {303 vm.run_in_state(|| {115 vm.run_in_state(|| {304 use std::fmt::Write;305 let filename = CStr::from_ptr(filename);116 let filename = CStr::from_ptr(filename);306 match vm.evaluate_file_to_json(&PathBuf::from(filename.to_str().unwrap())) {117 match vm118 .evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))119 .and_then(|v| vm.with_tla(v))120 .and_then(|v| vm.manifest(v))121 {307 Ok(v) => {122 Ok(v) => {308 *error = 0;123 *error = 0;309 CString::new(&*v as &str).unwrap().into_raw()124 CString::new(&*v as &str).unwrap().into_raw()310 }125 }311 Err(e) => {126 Err(e) => {312 *error = 1;127 *error = 1;313 let mut out = String::new();128 let out = vm.stringify_err(&e);314 writeln!(out, "{:?}", e.0).unwrap();315 for i in (e.1).0.iter() {316 writeln!(out, "{:?}", i.0).unwrap();317 }318 CString::new(&out as &str).unwrap().into_raw()129 CString::new(&out as &str).unwrap().into_raw()319 }130 }320 }131 }332 error: &mut c_int,143 error: &mut c_int,333) -> *const c_char {144) -> *const c_char {334 vm.run_in_state(|| {145 vm.run_in_state(|| {335 use std::fmt::Write;336 let filename = CStr::from_ptr(filename);146 let filename = CStr::from_ptr(filename);337 let snippet = CStr::from_ptr(snippet);147 let snippet = CStr::from_ptr(snippet);338 match vm.evaluate_snippet_to_json(148 match vm149 .evaluate_snippet_raw(339 &PathBuf::from(filename.to_str().unwrap()),150 Rc::new(PathBuf::from(filename.to_str().unwrap())),340 &snippet.to_str().unwrap(),151 snippet.to_str().unwrap().into(),341 ) {152 )153 .and_then(|v| vm.with_tla(v))154 .and_then(|v| vm.manifest(v))155 {342 Ok(v) => {156 Ok(v) => {343 *error = 0;157 *error = 0;344 CString::new(&*v as &str).unwrap().into_raw()158 CString::new(&*v as &str).unwrap().into_raw()345 }159 }346 Err(e) => {160 Err(e) => {347 *error = 1;161 *error = 1;348 let mut out = String::new();162 let out = vm.stringify_err(&e);349 writeln!(out, "{:?}", e.0).unwrap();350 for i in (e.1).0.iter() {351 writeln!(out, "{:?} ---- {}", i.0, i.1).unwrap();352 }353 CString::new(&out as &str).unwrap().into_raw()163 CString::new(&out as &str).unwrap().into_raw()354 }164 }355 }165 }bindings/jsonnet/src/val_extract.rsdiffbeforeafterbothno changes
bindings/jsonnet/src/val_make.rsdiffbeforeafterbothno changes
bindings/jsonnet/src/val_modify.rsdiffbeforeafterbothno changes
bindings/jsonnet/src/vars_tlas.rsdiffbeforeafterbothno changes
bindings/test.jsonnetdiffbeforeafterbothno changes
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth57 FractionalIndex,57 FractionalIndex,58 DivisionByZero,58 DivisionByZero,5960 StringManifestOutputIsNotAString,6162 ImportCallbackError(String),59}63}606461#[derive(Clone, Debug)]65#[derive(Clone, Debug)]62pub struct StackTraceElement(pub ExprLocation, pub String);66pub struct StackTraceElement {67 pub location: ExprLocation,68 pub desc: String,69}63#[derive(Debug, Clone)]70#[derive(Debug, Clone)]64pub struct StackTrace(pub Vec<StackTraceElement>);71pub struct StackTrace(pub Vec<StackTraceElement>);6572