feat: eval_shallow & eval_deep
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -5,3 +5,5 @@ target/
|
||||
# Profiling
|
||||
flamegraph*.svg
|
||||
perf.data*
|
||||
profile.json.gz
|
||||
prof.json
|
||||
|
||||
@@ -7,19 +7,19 @@ use nix_js::value::Value;
|
||||
pub fn eval(expr: &str) -> Value {
|
||||
Context::new()
|
||||
.unwrap()
|
||||
.eval_code(Source::new_eval(expr.into()).unwrap())
|
||||
.eval(Source::new_eval(expr.into()).unwrap())
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn eval_result(expr: &str) -> Result<Value> {
|
||||
Context::new()
|
||||
.unwrap()
|
||||
.eval_code(Source::new_eval(expr.into()).unwrap())
|
||||
.eval(Source::new_eval(expr.into()).unwrap())
|
||||
}
|
||||
|
||||
pub fn compile(expr: &str) -> String {
|
||||
Context::new()
|
||||
.unwrap()
|
||||
.compile_code(Source::new_eval(expr.into()).unwrap())
|
||||
.compile(Source::new_eval(expr.into()).unwrap())
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* All functionality is exported via the global `Nix` object
|
||||
*/
|
||||
|
||||
import { createThunk, force, isThunk, IS_THUNK, DEBUG_THUNKS, forceDeepSafe, IS_CYCLE } from "./thunk";
|
||||
import { createThunk, force, isThunk, IS_THUNK, DEBUG_THUNKS, forceDeep, IS_CYCLE, forceShallow } from "./thunk";
|
||||
import {
|
||||
select,
|
||||
selectWithDefault,
|
||||
@@ -34,7 +34,8 @@ export type NixRuntime = typeof Nix;
|
||||
export const Nix = {
|
||||
createThunk,
|
||||
force,
|
||||
forceDeepSafe,
|
||||
forceShallow,
|
||||
forceDeep,
|
||||
forceBool,
|
||||
isThunk,
|
||||
IS_THUNK,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import type { NixValue, NixThunkInterface, NixStrictValue } from "./types";
|
||||
import { HAS_CONTEXT } from "./string-context";
|
||||
import { IS_PATH } from "./types";
|
||||
import { isAttrs } from "./builtins/type-check";
|
||||
|
||||
/**
|
||||
* Symbol used to mark objects as thunks
|
||||
@@ -151,7 +152,7 @@ export const CYCLE_MARKER = { [IS_CYCLE]: true };
|
||||
* Returns a fully forced value where thunks are replaced with their results.
|
||||
* Cyclic references are replaced with CYCLE_MARKER, preserving the container type.
|
||||
*/
|
||||
export const forceDeepSafe = (value: NixValue, seen: WeakSet<object> = new WeakSet()): NixStrictValue => {
|
||||
export const forceDeep = (value: NixValue, seen: WeakSet<object> = new WeakSet()): NixStrictValue => {
|
||||
const forced = force(value);
|
||||
|
||||
if (forced === null || typeof forced !== "object") {
|
||||
@@ -171,13 +172,43 @@ export const forceDeepSafe = (value: NixValue, seen: WeakSet<object> = new WeakS
|
||||
}
|
||||
|
||||
if (Array.isArray(forced)) {
|
||||
return forced.map((item) => forceDeepSafe(item, seen));
|
||||
return forced.map((item) => forceDeep(item, seen));
|
||||
}
|
||||
|
||||
if (typeof forced === "object") {
|
||||
const result: Record<string, NixValue> = {};
|
||||
for (const [key, val] of Object.entries(forced)) {
|
||||
result[key] = forceDeepSafe(val, seen);
|
||||
result[key] = forceDeep(val, seen);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return forced;
|
||||
};
|
||||
|
||||
export const forceShallow = (value: NixValue): NixStrictValue => {
|
||||
const forced = force(value);
|
||||
|
||||
if (forced === null || typeof forced !== "object") {
|
||||
return forced;
|
||||
}
|
||||
|
||||
if (Array.isArray(forced)) {
|
||||
return forced.map((item) => {
|
||||
const forcedItem = force(item);
|
||||
if (typeof forcedItem === "object" && forcedItem === forced) {
|
||||
return CYCLE_MARKER
|
||||
} else {
|
||||
return forcedItem
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (isAttrs(forced)) {
|
||||
const result: Record<string, NixValue> = {};
|
||||
for (const [key, val] of Object.entries(forced)) {
|
||||
const forcedVal = force(val);
|
||||
result[key] = forcedVal === forced ? CYCLE_MARKER : forcedVal;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ fn main() -> Result<()> {
|
||||
args.next();
|
||||
let expr = args.next().unwrap();
|
||||
let src = Source::new_eval(expr)?;
|
||||
match Context::new()?.eval_code(src) {
|
||||
match Context::new()?.eval(src) {
|
||||
Ok(value) => {
|
||||
println!("{value}");
|
||||
Ok(())
|
||||
|
||||
@@ -33,7 +33,7 @@ fn main() -> Result<()> {
|
||||
} */
|
||||
} else {
|
||||
let src = Source::new_repl(line)?;
|
||||
match context.eval_code(src) {
|
||||
match context.eval_shallow(src) {
|
||||
Ok(value) => println!("{value}"),
|
||||
Err(err) => eprintln!("{:?}", miette::Report::new(*err)),
|
||||
}
|
||||
|
||||
@@ -21,6 +21,21 @@ pub struct Context {
|
||||
runtime: Runtime<Ctx>,
|
||||
}
|
||||
|
||||
macro_rules! eval {
|
||||
($name:ident, $wrapper:literal) => {
|
||||
pub fn $name(&mut self, source: Source) -> Result<Value> {
|
||||
tracing::info!("Starting evaluation");
|
||||
|
||||
tracing::debug!("Compiling code");
|
||||
let code = self.compile(source)?;
|
||||
|
||||
tracing::debug!("Executing JavaScript");
|
||||
self.runtime
|
||||
.eval(format!($wrapper, code), &mut self.ctx)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn new() -> Result<Self> {
|
||||
let ctx = Ctx::new()?;
|
||||
@@ -29,19 +44,12 @@ impl Context {
|
||||
Ok(Self { ctx, runtime })
|
||||
}
|
||||
|
||||
pub fn eval_code(&mut self, source: Source) -> Result<Value> {
|
||||
tracing::info!("Starting evaluation");
|
||||
eval!(eval, "Nix.force({})");
|
||||
eval!(eval_shallow, "Nix.forceShallow({})");
|
||||
eval!(eval_deep, "Nix.forceDeep({})");
|
||||
|
||||
tracing::debug!("Compiling code");
|
||||
let code = self.compile_code(source)?;
|
||||
|
||||
tracing::debug!("Executing JavaScript");
|
||||
self.runtime
|
||||
.eval(format!("Nix.forceDeepSafe({code})"), &mut self.ctx)
|
||||
}
|
||||
|
||||
pub fn compile_code(&mut self, source: Source) -> Result<String> {
|
||||
self.ctx.compile_code(source)
|
||||
pub fn compile(&mut self, source: Source) -> Result<String> {
|
||||
self.ctx.compile(source)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -183,7 +191,7 @@ impl Ctx {
|
||||
self.sources.get(id).expect("source not found").clone()
|
||||
}
|
||||
|
||||
fn compile_code(&mut self, source: Source) -> Result<String> {
|
||||
fn compile(&mut self, source: Source) -> Result<String> {
|
||||
tracing::debug!("Parsing Nix expression");
|
||||
|
||||
self.sources.push(source.clone());
|
||||
@@ -239,7 +247,7 @@ impl RuntimeContext for Ctx {
|
||||
self.sources.push(source);
|
||||
}
|
||||
fn compile_code(&mut self, source: Source) -> Result<String> {
|
||||
self.compile_code(source)
|
||||
self.compile(source)
|
||||
}
|
||||
fn get_source(&self, id: usize) -> Source {
|
||||
self.get_source(id)
|
||||
|
||||
@@ -117,11 +117,30 @@ impl Debug for AttrSet {
|
||||
|
||||
impl Display for AttrSet {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "{{")?;
|
||||
for (k, v) in self.data.iter() {
|
||||
write!(f, " {k} = {v};")?;
|
||||
use Value::*;
|
||||
if self.data.len() > 1 {
|
||||
writeln!(f, "{{")?;
|
||||
for (k, v) in self.data.iter() {
|
||||
write!(f, " {k} = ")?;
|
||||
match v {
|
||||
List(_) => writeln!(f, "[ ... ];")?,
|
||||
AttrSet(_) => writeln!(f, "{{ ... }};")?,
|
||||
v => writeln!(f, "{v};")?,
|
||||
}
|
||||
}
|
||||
write!(f, "}}")
|
||||
} else {
|
||||
write!(f, "{{")?;
|
||||
for (k, v) in self.data.iter() {
|
||||
write!(f, " {k} = ")?;
|
||||
match v {
|
||||
List(_) => write!(f, "[ ... ];")?,
|
||||
AttrSet(_) => write!(f, "{{ ... }};")?,
|
||||
v => write!(f, "{v};")?,
|
||||
}
|
||||
}
|
||||
write!(f, " }}")
|
||||
}
|
||||
write!(f, " }}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,11 +182,28 @@ impl DerefMut for List {
|
||||
|
||||
impl Display for List {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "[ ")?;
|
||||
for v in self.data.iter() {
|
||||
write!(f, "{v} ")?;
|
||||
use Value::*;
|
||||
if self.data.len() > 1 {
|
||||
writeln!(f, "[")?;
|
||||
for v in self.data.iter() {
|
||||
match v {
|
||||
List(_) => writeln!(f, " [ ... ]")?,
|
||||
AttrSet(_) => writeln!(f, " {{ ... }}")?,
|
||||
v => writeln!(f, " {v}")?,
|
||||
}
|
||||
}
|
||||
write!(f, "]")
|
||||
} else {
|
||||
write!(f, "[ ")?;
|
||||
for v in self.data.iter() {
|
||||
match v {
|
||||
List(_) => write!(f, "[ ... ] ")?,
|
||||
AttrSet(_) => write!(f, "{{ ... }} ")?,
|
||||
v => write!(f, "{v} ")?,
|
||||
}
|
||||
}
|
||||
write!(f, "]")
|
||||
}
|
||||
write!(f, "]")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
mod utils;
|
||||
|
||||
use nix_js::value::Value;
|
||||
use utils::{eval, eval_result};
|
||||
use utils::{eval_deep, eval_deep_result};
|
||||
|
||||
#[test]
|
||||
fn derivation_minimal() {
|
||||
let result =
|
||||
eval(r#"derivation { name = "hello"; builder = "/bin/sh"; system = "x86_64-linux"; }"#);
|
||||
eval_deep(r#"derivation { name = "hello"; builder = "/bin/sh"; system = "x86_64-linux"; }"#);
|
||||
|
||||
match result {
|
||||
Value::AttrSet(attrs) => {
|
||||
@@ -44,7 +44,7 @@ fn derivation_minimal() {
|
||||
|
||||
#[test]
|
||||
fn derivation_with_args() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "test";
|
||||
builder = "/bin/sh";
|
||||
@@ -66,7 +66,7 @@ fn derivation_with_args() {
|
||||
|
||||
#[test]
|
||||
fn derivation_to_string() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"toString (derivation { name = "foo"; builder = "/bin/sh"; system = "x86_64-linux"; })"#,
|
||||
);
|
||||
|
||||
@@ -78,7 +78,7 @@ fn derivation_to_string() {
|
||||
|
||||
#[test]
|
||||
fn derivation_missing_name() {
|
||||
let result = eval_result(r#"derivation { builder = "/bin/sh"; system = "x86_64-linux"; }"#);
|
||||
let result = eval_deep_result(r#"derivation { builder = "/bin/sh"; system = "x86_64-linux"; }"#);
|
||||
|
||||
assert!(result.is_err());
|
||||
let err_msg = result.unwrap_err().to_string();
|
||||
@@ -87,7 +87,7 @@ fn derivation_missing_name() {
|
||||
|
||||
#[test]
|
||||
fn derivation_invalid_name_with_drv_suffix() {
|
||||
let result = eval_result(
|
||||
let result = eval_deep_result(
|
||||
r#"derivation { name = "foo.drv"; builder = "/bin/sh"; system = "x86_64-linux"; }"#,
|
||||
);
|
||||
|
||||
@@ -98,7 +98,7 @@ fn derivation_invalid_name_with_drv_suffix() {
|
||||
|
||||
#[test]
|
||||
fn derivation_missing_builder() {
|
||||
let result = eval_result(r#"derivation { name = "test"; system = "x86_64-linux"; }"#);
|
||||
let result = eval_deep_result(r#"derivation { name = "test"; system = "x86_64-linux"; }"#);
|
||||
|
||||
assert!(result.is_err());
|
||||
let err_msg = result.unwrap_err().to_string();
|
||||
@@ -107,7 +107,7 @@ fn derivation_missing_builder() {
|
||||
|
||||
#[test]
|
||||
fn derivation_missing_system() {
|
||||
let result = eval_result(r#"derivation { name = "test"; builder = "/bin/sh"; }"#);
|
||||
let result = eval_deep_result(r#"derivation { name = "test"; builder = "/bin/sh"; }"#);
|
||||
|
||||
assert!(result.is_err());
|
||||
let err_msg = result.unwrap_err().to_string();
|
||||
@@ -116,7 +116,7 @@ fn derivation_missing_system() {
|
||||
|
||||
#[test]
|
||||
fn derivation_with_env_vars() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "test";
|
||||
builder = "/bin/sh";
|
||||
@@ -137,7 +137,7 @@ fn derivation_with_env_vars() {
|
||||
|
||||
#[test]
|
||||
fn derivation_strict() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"builtins.derivationStrict { name = "test"; builder = "/bin/sh"; system = "x86_64-linux"; }"#,
|
||||
);
|
||||
|
||||
@@ -156,8 +156,8 @@ fn derivation_strict() {
|
||||
fn derivation_deterministic_paths() {
|
||||
let expr = r#"derivation { name = "hello"; builder = "/bin/sh"; system = "x86_64-linux"; }"#;
|
||||
|
||||
let result1 = eval(expr);
|
||||
let result2 = eval(expr);
|
||||
let result1 = eval_deep(expr);
|
||||
let result2 = eval_deep(expr);
|
||||
|
||||
match (result1, result2) {
|
||||
(Value::AttrSet(attrs1), Value::AttrSet(attrs2)) => {
|
||||
@@ -170,7 +170,7 @@ fn derivation_deterministic_paths() {
|
||||
|
||||
#[test]
|
||||
fn derivation_escaping_in_aterm() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "test";
|
||||
builder = "/bin/sh";
|
||||
@@ -190,7 +190,7 @@ fn derivation_escaping_in_aterm() {
|
||||
|
||||
#[test]
|
||||
fn multi_output_two_outputs() {
|
||||
let drv = eval(
|
||||
let drv = eval_deep(
|
||||
r#"derivation {
|
||||
name = "multi";
|
||||
builder = "/bin/sh";
|
||||
@@ -233,7 +233,7 @@ fn multi_output_two_outputs() {
|
||||
|
||||
#[test]
|
||||
fn multi_output_three_outputs() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "three";
|
||||
builder = "/bin/sh";
|
||||
@@ -281,7 +281,7 @@ fn multi_output_three_outputs() {
|
||||
|
||||
#[test]
|
||||
fn multi_output_backward_compat() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "compat";
|
||||
builder = "/bin/sh";
|
||||
@@ -307,7 +307,7 @@ fn multi_output_backward_compat() {
|
||||
|
||||
#[test]
|
||||
fn multi_output_deterministic() {
|
||||
let result1 = eval(
|
||||
let result1 = eval_deep(
|
||||
r#"derivation {
|
||||
name = "determ";
|
||||
builder = "/bin/sh";
|
||||
@@ -316,7 +316,7 @@ fn multi_output_deterministic() {
|
||||
}"#,
|
||||
);
|
||||
|
||||
let result2 = eval(
|
||||
let result2 = eval_deep(
|
||||
r#"derivation {
|
||||
name = "determ";
|
||||
builder = "/bin/sh";
|
||||
@@ -330,7 +330,7 @@ fn multi_output_deterministic() {
|
||||
|
||||
#[test]
|
||||
fn fixed_output_sha256_flat() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "fixed";
|
||||
builder = "/bin/sh";
|
||||
@@ -367,7 +367,7 @@ fn fixed_output_sha256_flat() {
|
||||
|
||||
#[test]
|
||||
fn fixed_output_default_algo() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "default";
|
||||
builder = "/bin/sh";
|
||||
@@ -390,7 +390,7 @@ fn fixed_output_default_algo() {
|
||||
|
||||
#[test]
|
||||
fn fixed_output_recursive_mode() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "recursive";
|
||||
builder = "/bin/sh";
|
||||
@@ -420,7 +420,7 @@ fn fixed_output_recursive_mode() {
|
||||
|
||||
#[test]
|
||||
fn fixed_output_rejects_multi_output() {
|
||||
let result = eval_result(
|
||||
let result = eval_deep_result(
|
||||
r#"derivation {
|
||||
name = "invalid";
|
||||
builder = "/bin/sh";
|
||||
@@ -437,7 +437,7 @@ fn fixed_output_rejects_multi_output() {
|
||||
|
||||
#[test]
|
||||
fn fixed_output_invalid_hash_mode() {
|
||||
let result = eval_result(
|
||||
let result = eval_deep_result(
|
||||
r#"derivation {
|
||||
name = "invalid";
|
||||
builder = "/bin/sh";
|
||||
@@ -454,7 +454,7 @@ fn fixed_output_invalid_hash_mode() {
|
||||
|
||||
#[test]
|
||||
fn structured_attrs_basic() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "struct";
|
||||
builder = "/bin/sh";
|
||||
@@ -479,7 +479,7 @@ fn structured_attrs_basic() {
|
||||
|
||||
#[test]
|
||||
fn structured_attrs_nested() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "nested";
|
||||
builder = "/bin/sh";
|
||||
@@ -500,7 +500,7 @@ fn structured_attrs_nested() {
|
||||
|
||||
#[test]
|
||||
fn structured_attrs_rejects_functions() {
|
||||
let result = eval_result(
|
||||
let result = eval_deep_result(
|
||||
r#"derivation {
|
||||
name = "invalid";
|
||||
builder = "/bin/sh";
|
||||
@@ -517,7 +517,7 @@ fn structured_attrs_rejects_functions() {
|
||||
|
||||
#[test]
|
||||
fn structured_attrs_false() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "normal";
|
||||
builder = "/bin/sh";
|
||||
@@ -540,7 +540,7 @@ fn structured_attrs_false() {
|
||||
|
||||
#[test]
|
||||
fn ignore_nulls_true() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "ignore";
|
||||
builder = "/bin/sh";
|
||||
@@ -562,7 +562,7 @@ fn ignore_nulls_true() {
|
||||
|
||||
#[test]
|
||||
fn ignore_nulls_false() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "keep";
|
||||
builder = "/bin/sh";
|
||||
@@ -585,7 +585,7 @@ fn ignore_nulls_false() {
|
||||
|
||||
#[test]
|
||||
fn ignore_nulls_with_structured_attrs() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "combined";
|
||||
builder = "/bin/sh";
|
||||
@@ -609,7 +609,7 @@ fn ignore_nulls_with_structured_attrs() {
|
||||
|
||||
#[test]
|
||||
fn all_features_combined() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "all";
|
||||
builder = "/bin/sh";
|
||||
@@ -636,7 +636,7 @@ fn all_features_combined() {
|
||||
|
||||
#[test]
|
||||
fn fixed_output_with_structured_attrs() {
|
||||
let result = eval(
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
name = "fixstruct";
|
||||
builder = "/bin/sh";
|
||||
|
||||
@@ -105,7 +105,7 @@ fn path_with_file() {
|
||||
std::fs::write(&test_file, "Hello, World!").unwrap();
|
||||
|
||||
let expr = format!(r#"builtins.path {{ path = {}; }}"#, test_file.display());
|
||||
let result = ctx.eval_code(Source::new_eval(expr).unwrap()).unwrap();
|
||||
let result = ctx.eval(Source::new_eval(expr).unwrap()).unwrap();
|
||||
|
||||
// Should return a store path string
|
||||
if let Value::String(store_path) = result {
|
||||
@@ -149,7 +149,7 @@ fn path_with_directory_recursive() {
|
||||
r#"builtins.path {{ path = {}; recursive = true; }}"#,
|
||||
test_dir.display()
|
||||
);
|
||||
let result = ctx.eval_code(Source::new_eval(expr).unwrap()).unwrap();
|
||||
let result = ctx.eval(Source::new_eval(expr).unwrap()).unwrap();
|
||||
|
||||
if let Value::String(store_path) = result {
|
||||
assert!(store_path.starts_with(ctx.get_store_dir()));
|
||||
@@ -170,7 +170,7 @@ fn path_flat_with_file() {
|
||||
r#"builtins.path {{ path = {}; recursive = false; }}"#,
|
||||
test_file.display()
|
||||
);
|
||||
let result = ctx.eval_code(Source::new_eval(expr).unwrap()).unwrap();
|
||||
let result = ctx.eval(Source::new_eval(expr).unwrap()).unwrap();
|
||||
|
||||
if let Value::String(store_path) = result {
|
||||
assert!(store_path.starts_with(ctx.get_store_dir()));
|
||||
|
||||
@@ -23,7 +23,7 @@ fn eval_file(name: &str) -> Result<(Value, Source), String> {
|
||||
ty: nix_js::error::SourceType::File(nix_path.into()),
|
||||
src: expr.into(),
|
||||
};
|
||||
ctx.eval_code(source.clone())
|
||||
ctx.eval_deep(source.clone())
|
||||
.map(|val| (val, source))
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ fn string_add_merges_context() {
|
||||
fn context_in_derivation_args() {
|
||||
let mut ctx = Context::new().unwrap();
|
||||
let result = ctx
|
||||
.eval_code(
|
||||
.eval(
|
||||
r#"
|
||||
let
|
||||
dep = derivation { name = "dep"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
@@ -185,7 +185,7 @@ fn context_in_derivation_args() {
|
||||
fn context_in_derivation_env() {
|
||||
let mut ctx = Context::new().unwrap();
|
||||
let result = ctx
|
||||
.eval_code(
|
||||
.eval(
|
||||
r#"
|
||||
let
|
||||
dep = derivation { name = "dep"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
@@ -227,7 +227,7 @@ fn tostring_preserves_context() {
|
||||
fn interpolation_derivation_returns_outpath() {
|
||||
let mut ctx = Context::new().unwrap();
|
||||
let result = ctx
|
||||
.eval_code(
|
||||
.eval(
|
||||
r#"
|
||||
let
|
||||
drv = derivation { name = "test"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
|
||||
@@ -7,12 +7,25 @@ use nix_js::value::Value;
|
||||
pub fn eval(expr: &str) -> Value {
|
||||
Context::new()
|
||||
.unwrap()
|
||||
.eval_code(Source::new_eval(expr.into()).unwrap())
|
||||
.eval(Source::new_eval(expr.into()).unwrap())
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn eval_deep(expr: &str) -> Value {
|
||||
Context::new()
|
||||
.unwrap()
|
||||
.eval_deep(Source::new_eval(expr.into()).unwrap())
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn eval_deep_result(expr: &str) -> Result<Value> {
|
||||
Context::new()
|
||||
.unwrap()
|
||||
.eval_deep(Source::new_eval(expr.into()).unwrap())
|
||||
}
|
||||
|
||||
pub fn eval_result(expr: &str) -> Result<Value> {
|
||||
Context::new()
|
||||
.unwrap()
|
||||
.eval_code(Source::new_eval(expr.into()).unwrap())
|
||||
.eval(Source::new_eval(expr.into()).unwrap())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user