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