refactor(downgrade): use bumpalo

This commit is contained in:
2026-02-20 19:05:43 +08:00
parent e1517c338e
commit 53dbee3514
29 changed files with 1087 additions and 985 deletions

53
Cargo.lock generated
View File

@@ -289,9 +289,12 @@ dependencies = [
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.19.1" version = "3.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
dependencies = [
"allocator-api2",
]
[[package]] [[package]]
name = "bytes" name = "bytes"
@@ -959,6 +962,27 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
[[package]]
name = "env_filter"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f"
dependencies = [
"log",
]
[[package]]
name = "env_logger"
version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d"
dependencies = [
"anstream",
"anstyle",
"env_filter",
"log",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.2" version = "1.0.2"
@@ -2022,6 +2046,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64 0.22.1", "base64 0.22.1",
"bumpalo",
"bzip2", "bzip2",
"clap", "clap",
"criterion", "criterion",
@@ -2061,6 +2086,7 @@ dependencies = [
"tap", "tap",
"tar", "tar",
"tempfile", "tempfile",
"test-log",
"thiserror 2.0.18", "thiserror 2.0.18",
"tokio", "tokio",
"toml", "toml",
@@ -2075,6 +2101,7 @@ name = "nix-js-macros"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"convert_case 0.11.0", "convert_case 0.11.0",
"proc-macro2",
"quote", "quote",
"syn", "syn",
] ]
@@ -3393,6 +3420,28 @@ dependencies = [
"windows-sys 0.60.2", "windows-sys 0.60.2",
] ]
[[package]]
name = "test-log"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d53ac171c92a39e4769491c4b4dde7022c60042254b5fc044ae409d34a24d4"
dependencies = [
"env_logger",
"test-log-macros",
"tracing-subscriber",
]
[[package]]
name = "test-log-macros"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be35209fd0781c5401458ab66e4f98accf63553e8fae7425503e92fdd319783b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "text-size" name = "text-size"
version = "1.1.1" version = "1.1.1"

View File

@@ -8,5 +8,6 @@ proc-macro = true
[dependencies] [dependencies]
convert_case = "0.11" convert_case = "0.11"
proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
syn = { version = "2.0", features = ["full"] } syn = { version = "2.0", features = ["full"] }

View File

@@ -4,22 +4,22 @@
//! an Intermediate Representation (IR) that follows a specific pattern. It generates: //! an Intermediate Representation (IR) that follows a specific pattern. It generates:
//! 1. An enum representing the different kinds of IR nodes. //! 1. An enum representing the different kinds of IR nodes.
//! 2. Structs for each of the variants that have fields. //! 2. Structs for each of the variants that have fields.
//! 3. `Ref` and `Mut` versions of the main enum for ergonomic pattern matching on references. //! 3. `From` implementations to easily convert from a struct variant (e.g., `BinOp`) to the main enum (`Ir::BinOp`).
//! 4. `From` implementations to easily convert from a struct variant (e.g., `BinOp`) to the main enum (`Ir::BinOp`). //! 4. A `To[IrName]` trait to provide a convenient `.to_ir()` method on the variant structs.
//! 5. A `To[IrName]` trait to provide a convenient `.to_ir()` method on the variant structs.
use convert_case::{Case, Casing}; use convert_case::{Case, Casing};
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::{format_ident, quote}; use quote::{format_ident, quote};
use syn::{ use syn::{
FieldsNamed, Ident, Token, Type, parenthesized, Expr, ExprPath, FieldsNamed, GenericArgument, GenericParam, Generics, Ident, Path, PathSegment,
Token, Type, TypePath, parenthesized,
parse::{Parse, ParseStream, Result}, parse::{Parse, ParseStream, Result},
punctuated::Punctuated, punctuated::Punctuated,
token, token,
}; };
/// Represents one of the variants passed to the `ir!` macro. /// Represents one of the variants passed to the `ir!` macro.
pub enum VariantInput { enum VariantInput {
/// A unit-like variant, e.g., `Arg`. /// A unit-like variant, e.g., `Arg`.
Unit(Ident), Unit(Ident),
/// A tuple-like variant with one unnamed field, e.g., `ExprRef(ExprId)`. /// A tuple-like variant with one unnamed field, e.g., `ExprRef(ExprId)`.
@@ -29,11 +29,12 @@ pub enum VariantInput {
} }
/// The top-level input for the `ir!` macro. /// The top-level input for the `ir!` macro.
pub struct MacroInput { struct MacroInput {
/// The name of the main IR enum to be generated (e.g., `Ir`). /// The name of the main IR enum to be generated (e.g., `Ir`).
pub base_name: Ident, base_name: Ident,
generics: Generics,
/// The list of variants for the enum. /// The list of variants for the enum.
pub variants: Punctuated<VariantInput, Token![,]>, variants: Punctuated<VariantInput, Token![,]>,
} }
impl Parse for VariantInput { impl Parse for VariantInput {
@@ -64,13 +65,14 @@ impl Parse for VariantInput {
impl Parse for MacroInput { impl Parse for MacroInput {
fn parse(input: ParseStream) -> Result<Self> { fn parse(input: ParseStream) -> Result<Self> {
// The macro input is expected to be: `IrName, Variant1, Variant2, ...`
let base_name = input.parse()?; let base_name = input.parse()?;
input.parse::<Token![,]>()?; let generics = Generics::parse(input)?;
input.parse::<Token![;]>()?;
let variants = Punctuated::parse_terminated(input)?; let variants = Punctuated::parse_terminated(input)?;
Ok(MacroInput { Ok(MacroInput {
base_name, base_name,
generics,
variants, variants,
}) })
} }
@@ -81,17 +83,39 @@ pub fn ir_impl(input: TokenStream) -> TokenStream {
let parsed_input = syn::parse_macro_input!(input as MacroInput); let parsed_input = syn::parse_macro_input!(input as MacroInput);
let base_name = &parsed_input.base_name; let base_name = &parsed_input.base_name;
let ref_name = format_ident!("{}Ref", base_name); let generic_params = &parsed_input.generics.params;
let mut_name = format_ident!("{}Mut", base_name); let mk_ident_path = |ident| Path {
leading_colon: None,
segments: Punctuated::from_iter(std::iter::once(PathSegment {
ident,
arguments: Default::default(),
})),
};
let generic_args = {
generic_params
.iter()
.map(|arg| match arg {
GenericParam::Lifetime(lifetime) => {
GenericArgument::Lifetime(lifetime.lifetime.clone())
}
GenericParam::Const(cnst) => GenericArgument::Const(Expr::Path(ExprPath {
path: mk_ident_path(cnst.ident.clone()),
attrs: Vec::new(),
qself: None,
})),
GenericParam::Type(ty) => GenericArgument::Type(Type::Path(TypePath {
path: mk_ident_path(ty.ident.clone()),
qself: None,
})),
})
.collect::<Punctuated<_, Token![,]>>()
};
let where_clause = &parsed_input.generics.where_clause;
let to_trait_name = format_ident!("To{}", base_name); let to_trait_name = format_ident!("To{}", base_name);
let to_trait_fn_name = format_ident!("to_{}", base_name.to_string().to_case(Case::Snake)); let to_trait_fn_name = format_ident!("to_{}", base_name.to_string().to_case(Case::Snake));
let mut enum_variants = Vec::new(); let mut enum_variants = Vec::new();
let mut struct_defs = Vec::new(); let mut struct_defs = Vec::new();
let mut ref_variants = Vec::new();
let mut mut_variants = Vec::new();
let mut as_ref_arms = Vec::new();
let mut as_mut_arms = Vec::new();
let mut span_arms = Vec::new(); let mut span_arms = Vec::new();
let mut from_impls = Vec::new(); let mut from_impls = Vec::new();
let mut to_trait_impls = Vec::new(); let mut to_trait_impls = Vec::new();
@@ -109,19 +133,15 @@ pub fn ir_impl(input: TokenStream) -> TokenStream {
}); });
enum_variants.push(quote! { #name(#inner_type) }); enum_variants.push(quote! { #name(#inner_type) });
ref_variants.push(quote! { #name(&'a #inner_type) });
mut_variants.push(quote! { #name(&'a mut #inner_type) });
as_ref_arms.push(quote! { Self::#name(inner) => #ref_name::#name(inner) });
as_mut_arms.push(quote! { Self::#name(inner) => #mut_name::#name(inner) });
span_arms.push(quote! { Self::#name(inner) => inner.span }); span_arms.push(quote! { Self::#name(inner) => inner.span });
from_impls.push(quote! { from_impls.push(quote! {
impl From<#inner_type> for #base_name { impl <#generic_params> From<#inner_type> for #base_name <#generic_args> #where_clause {
fn from(val: #inner_type) -> Self { #base_name::#name(val) } fn from(val: #inner_type) -> Self { #base_name::#name(val) }
} }
}); });
to_trait_impls.push(quote! { to_trait_impls.push(quote! {
impl #to_trait_name for #name { impl <#generic_params> #to_trait_name <#generic_args> for #name #where_clause {
fn #to_trait_fn_name(self) -> #base_name { #base_name::from(self) } fn #to_trait_fn_name(self) -> #base_name <#generic_args> { #base_name::from(self) }
} }
}); });
} }
@@ -138,25 +158,24 @@ pub fn ir_impl(input: TokenStream) -> TokenStream {
let inner_type = name.clone(); let inner_type = name.clone();
enum_variants.push(quote! { #name(#inner_type) }); enum_variants.push(quote! { #name(#inner_type) });
ref_variants.push(quote! { #name(&'a #inner_type) });
mut_variants.push(quote! { #name(&'a mut #inner_type) });
as_ref_arms.push(quote! { Self::#name(inner) => #ref_name::#name(inner) });
as_mut_arms.push(quote! { Self::#name(inner) => #mut_name::#name(inner) });
span_arms.push(quote! { Self::#name(inner) => inner.span }); span_arms.push(quote! { Self::#name(inner) => inner.span });
from_impls.push(quote! { from_impls.push(quote! {
impl From<#inner_type> for #base_name { impl <#generic_params> From<#inner_type> for #base_name <#generic_args> #where_clause {
fn from(val: #inner_type) -> Self { #base_name::#name(val) } fn from(val: #inner_type) -> Self { #base_name::#name(val) }
} }
}); });
to_trait_impls.push(quote! { to_trait_impls.push(quote! {
impl #to_trait_name for #name { impl <#generic_params> #to_trait_name <#generic_args> for #name #where_clause {
fn #to_trait_fn_name(self) -> #base_name { #base_name::from(self) } fn #to_trait_fn_name(self) -> #base_name <#generic_args> { #base_name::from(self) }
} }
}); });
} }
VariantInput::Struct(name, mut fields) => { VariantInput::Struct(name, mut fields) => {
let inner_type = name.clone(); let inner_type = name.clone();
fields.named.iter_mut().for_each(|field| {
field.vis = syn::Visibility::Public(syn::token::Pub::default());
});
fields.named.push(syn::Field { fields.named.push(syn::Field {
attrs: vec![], attrs: vec![],
vis: syn::Visibility::Public(syn::token::Pub::default()), vis: syn::Visibility::Public(syn::token::Pub::default()),
@@ -168,22 +187,18 @@ pub fn ir_impl(input: TokenStream) -> TokenStream {
struct_defs.push(quote! { struct_defs.push(quote! {
#[derive(Debug)] #[derive(Debug)]
pub struct #name #fields pub struct #name <#generic_params> #where_clause #fields
}); });
enum_variants.push(quote! { #name(#inner_type) }); enum_variants.push(quote! { #name(#inner_type <#generic_args>) });
ref_variants.push(quote! { #name(&'a #inner_type) });
mut_variants.push(quote! { #name(&'a mut #inner_type) });
as_ref_arms.push(quote! { Self::#name(inner) => #ref_name::#name(inner) });
as_mut_arms.push(quote! { Self::#name(inner) => #mut_name::#name(inner) });
span_arms.push(quote! { Self::#name(inner) => inner.span }); span_arms.push(quote! { Self::#name(inner) => inner.span });
from_impls.push(quote! { from_impls.push(quote! {
impl From<#inner_type> for #base_name { impl <#generic_params> From<#inner_type <#generic_args>> for #base_name <#generic_args> #where_clause {
fn from(val: #inner_type) -> Self { #base_name::#name(val) } fn from(val: #inner_type <#generic_args>) -> Self { #base_name::#name(val) }
} }
}); });
to_trait_impls.push(quote! { to_trait_impls.push(quote! {
impl #to_trait_name for #name { impl <#generic_params> #to_trait_name <#generic_args> for #name <#generic_args> #where_clause {
fn #to_trait_fn_name(self) -> #base_name { #base_name::from(self) } fn #to_trait_fn_name(self) -> #base_name <#generic_args> { #base_name::from(self) }
} }
}); });
} }
@@ -193,41 +208,15 @@ pub fn ir_impl(input: TokenStream) -> TokenStream {
// Assemble the final generated code. // Assemble the final generated code.
let expanded = quote! { let expanded = quote! {
/// The main IR enum, generated by the `ir!` macro. /// The main IR enum, generated by the `ir!` macro.
#[derive(Debug, IsVariant, Unwrap, TryUnwrap)] #[derive(Debug)]
pub enum #base_name { pub enum #base_name <#generic_params> #where_clause {
#( #enum_variants ),* #( #enum_variants ),*
} }
// The struct definitions for the enum variants. // The struct definitions for the enum variants.
#( #struct_defs )* #( #struct_defs )*
/// An immutable reference version of the IR enum. impl <#generic_params> #base_name <#generic_args> #where_clause {
#[derive(Debug, IsVariant, Unwrap, TryUnwrap)]
pub enum #ref_name<'a> {
#( #ref_variants ),*
}
/// A mutable reference version of the IR enum.
#[derive(Debug, IsVariant, Unwrap, TryUnwrap)]
pub enum #mut_name<'a> {
#( #mut_variants ),*
}
impl #base_name {
/// Converts a `&Ir` into a `IrRef`.
pub fn as_ref(&self) -> #ref_name<'_> {
match self {
#( #as_ref_arms ),*
}
}
/// Converts a `&mut Ir` into a `IrMut`.
pub fn as_mut(&mut self) -> #mut_name<'_> {
match self {
#( #as_mut_arms ),*
}
}
pub fn span(&self) -> rnix::TextRange { pub fn span(&self) -> rnix::TextRange {
match self { match self {
#( #span_arms ),* #( #span_arms ),*
@@ -239,9 +228,9 @@ pub fn ir_impl(input: TokenStream) -> TokenStream {
#( #from_impls )* #( #from_impls )*
/// A trait for converting a variant struct into the main IR enum. /// A trait for converting a variant struct into the main IR enum.
pub trait #to_trait_name { pub trait #to_trait_name <#generic_params> #where_clause {
/// Performs the conversion. /// Performs the conversion.
fn #to_trait_fn_name(self) -> #base_name; fn #to_trait_fn_name(self) -> #base_name <#generic_args>;
} }
// Implement the `ToIr` trait for each variant struct. // Implement the `ToIr` trait for each variant struct.

View File

@@ -27,6 +27,7 @@ miette = { version = "7.4", features = ["fancy"] }
hashbrown = "0.16" hashbrown = "0.16"
string-interner = "0.19" string-interner = "0.19"
bumpalo = { version = "3.20", features = ["allocator-api2", "boxed", "collections"] }
rust-embed="8.11" rust-embed="8.11"
@@ -80,6 +81,7 @@ prof = []
[dev-dependencies] [dev-dependencies]
criterion = { version = "0.8", features = ["html_reports"] } criterion = { version = "0.8", features = ["html_reports"] }
test-log = { version = "0.2", features = ["trace"] }
[[bench]] [[bench]]
name = "basic_ops" name = "basic_ops"

View File

@@ -8,16 +8,15 @@
"name": "nix-js-runtime", "name": "nix-js-runtime",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@eslint/json": "^1.0.1",
"eslint": "^9.39.2",
"globals": "^17.3.0", "globals": "^17.3.0",
"jiti": "^2.6.1", "jiti": "^2.6.1",
"js-sdsl": "^4.4.2", "js-sdsl": "^4.4.2"
"typescript-eslint": "^8.55.0"
}, },
"devDependencies": { "devDependencies": {
"esbuild": "^0.24.2", "esbuild": "^0.24.2",
"typescript": "^5.7.2" "eslint": "^9.39.2",
"typescript": "^5.7.2",
"typescript-eslint": "^8.55.0"
} }
}, },
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
@@ -449,6 +448,7 @@
"version": "4.9.1", "version": "4.9.1",
"resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", "resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
"integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"eslint-visitor-keys": "^3.4.3" "eslint-visitor-keys": "^3.4.3"
@@ -467,6 +467,7 @@
"version": "3.4.3", "version": "3.4.3",
"resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -479,6 +480,7 @@
"version": "4.12.2", "version": "4.12.2",
"resolved": "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", "resolved": "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
"integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0" "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
@@ -488,6 +490,7 @@
"version": "0.21.1", "version": "0.21.1",
"resolved": "https://registry.npmmirror.com/@eslint/config-array/-/config-array-0.21.1.tgz", "resolved": "https://registry.npmmirror.com/@eslint/config-array/-/config-array-0.21.1.tgz",
"integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@eslint/object-schema": "^2.1.7", "@eslint/object-schema": "^2.1.7",
@@ -502,6 +505,7 @@
"version": "0.4.2", "version": "0.4.2",
"resolved": "https://registry.npmmirror.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", "resolved": "https://registry.npmmirror.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
"integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@eslint/core": "^0.17.0" "@eslint/core": "^0.17.0"
@@ -514,6 +518,7 @@
"version": "0.17.0", "version": "0.17.0",
"resolved": "https://registry.npmmirror.com/@eslint/core/-/core-0.17.0.tgz", "resolved": "https://registry.npmmirror.com/@eslint/core/-/core-0.17.0.tgz",
"integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@types/json-schema": "^7.0.15" "@types/json-schema": "^7.0.15"
@@ -522,22 +527,11 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
} }
}, },
"node_modules/@eslint/core": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/@eslint/core/-/core-1.1.0.tgz",
"integrity": "sha512-/nr9K9wkr3P1EzFTdFdMoLuo1PmIxjmwvPozwoSodjNBdefGujXQUF93u1DDZpEaTuDvMsIQddsd35BwtrW9Xw==",
"license": "Apache-2.0",
"dependencies": {
"@types/json-schema": "^7.0.15"
},
"engines": {
"node": "^20.19.0 || ^22.13.0 || >=24"
}
},
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {
"version": "3.3.3", "version": "3.3.3",
"resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
"integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ajv": "^6.12.4", "ajv": "^6.12.4",
@@ -561,6 +555,7 @@
"version": "14.0.0", "version": "14.0.0",
"resolved": "https://registry.npmmirror.com/globals/-/globals-14.0.0.tgz", "resolved": "https://registry.npmmirror.com/globals/-/globals-14.0.0.tgz",
"integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18" "node": ">=18"
@@ -573,6 +568,7 @@
"version": "9.39.2", "version": "9.39.2",
"resolved": "https://registry.npmmirror.com/@eslint/js/-/js-9.39.2.tgz", "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-9.39.2.tgz",
"integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -581,47 +577,21 @@
"url": "https://eslint.org/donate" "url": "https://eslint.org/donate"
} }
}, },
"node_modules/@eslint/json": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/@eslint/json/-/json-1.0.1.tgz",
"integrity": "sha512-bE2nGv8/U+uRvQEJWOgCsZCa65XsCBgxyyx/sXtTHVv0kqdauACLzyp7A1C3yNn7pRaWjIt5acxY+TAbSyIJXw==",
"license": "Apache-2.0",
"dependencies": {
"@eslint/core": "^1.1.0",
"@eslint/plugin-kit": "^0.6.0",
"@humanwhocodes/momoa": "^3.3.10",
"natural-compare": "^1.4.0"
},
"engines": {
"node": "^20.19.0 || ^22.13.0 || >=24"
}
},
"node_modules/@eslint/object-schema": { "node_modules/@eslint/object-schema": {
"version": "2.1.7", "version": "2.1.7",
"resolved": "https://registry.npmmirror.com/@eslint/object-schema/-/object-schema-2.1.7.tgz", "resolved": "https://registry.npmmirror.com/@eslint/object-schema/-/object-schema-2.1.7.tgz",
"integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
} }
}, },
"node_modules/@eslint/plugin-kit": {
"version": "0.6.0",
"resolved": "https://registry.npmmirror.com/@eslint/plugin-kit/-/plugin-kit-0.6.0.tgz",
"integrity": "sha512-bIZEUzOI1jkhviX2cp5vNyXQc6olzb2ohewQubuYlMXZ2Q/XjBO0x0XhGPvc9fjSIiUN0vw+0hq53BJ4eQSJKQ==",
"license": "Apache-2.0",
"dependencies": {
"@eslint/core": "^1.1.0",
"levn": "^0.4.1"
},
"engines": {
"node": "^20.19.0 || ^22.13.0 || >=24"
}
},
"node_modules/@humanfs/core": { "node_modules/@humanfs/core": {
"version": "0.19.1", "version": "0.19.1",
"resolved": "https://registry.npmmirror.com/@humanfs/core/-/core-0.19.1.tgz", "resolved": "https://registry.npmmirror.com/@humanfs/core/-/core-0.19.1.tgz",
"integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
"node": ">=18.18.0" "node": ">=18.18.0"
@@ -631,6 +601,7 @@
"version": "0.16.7", "version": "0.16.7",
"resolved": "https://registry.npmmirror.com/@humanfs/node/-/node-0.16.7.tgz", "resolved": "https://registry.npmmirror.com/@humanfs/node/-/node-0.16.7.tgz",
"integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@humanfs/core": "^0.19.1", "@humanfs/core": "^0.19.1",
@@ -644,6 +615,7 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "resolved": "https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
"node": ">=12.22" "node": ">=12.22"
@@ -653,19 +625,11 @@
"url": "https://github.com/sponsors/nzakas" "url": "https://github.com/sponsors/nzakas"
} }
}, },
"node_modules/@humanwhocodes/momoa": {
"version": "3.3.10",
"resolved": "https://registry.npmmirror.com/@humanwhocodes/momoa/-/momoa-3.3.10.tgz",
"integrity": "sha512-KWiFQpSAqEIyrTXko3hFNLeQvSK8zXlJQzhhxsyVn58WFRYXST99b3Nqnu+ttOtjds2Pl2grUHGpe2NzhPynuQ==",
"license": "Apache-2.0",
"engines": {
"node": ">=18"
}
},
"node_modules/@humanwhocodes/retry": { "node_modules/@humanwhocodes/retry": {
"version": "0.4.3", "version": "0.4.3",
"resolved": "https://registry.npmmirror.com/@humanwhocodes/retry/-/retry-0.4.3.tgz", "resolved": "https://registry.npmmirror.com/@humanwhocodes/retry/-/retry-0.4.3.tgz",
"integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
"node": ">=18.18" "node": ">=18.18"
@@ -679,18 +643,21 @@
"version": "1.0.8", "version": "1.0.8",
"resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz", "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz",
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/json-schema": { "node_modules/@types/json-schema": {
"version": "7.0.15", "version": "7.0.15",
"resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz", "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz",
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.55.0", "version": "8.55.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.55.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.55.0.tgz",
"integrity": "sha512-1y/MVSz0NglV1ijHC8OT49mPJ4qhPYjiK08YUQVbIOyu+5k862LKUHFkpKHWu//zmr7hDR2rhwUm6gnCGNmGBQ==", "integrity": "sha512-1y/MVSz0NglV1ijHC8OT49mPJ4qhPYjiK08YUQVbIOyu+5k862LKUHFkpKHWu//zmr7hDR2rhwUm6gnCGNmGBQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.12.2", "@eslint-community/regexpp": "^4.12.2",
@@ -719,6 +686,7 @@
"version": "7.0.5", "version": "7.0.5",
"resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz", "resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz",
"integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 4" "node": ">= 4"
@@ -728,6 +696,7 @@
"version": "8.55.0", "version": "8.55.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.55.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.55.0.tgz",
"integrity": "sha512-4z2nCSBfVIMnbuu8uinj+f0o4qOeggYJLbjpPHka3KH1om7e+H9yLKTYgksTaHcGco+NClhhY2vyO3HsMH1RGw==", "integrity": "sha512-4z2nCSBfVIMnbuu8uinj+f0o4qOeggYJLbjpPHka3KH1om7e+H9yLKTYgksTaHcGco+NClhhY2vyO3HsMH1RGw==",
"dev": true,
"license": "MIT", "license": "MIT",
"peer": true, "peer": true,
"dependencies": { "dependencies": {
@@ -753,6 +722,7 @@
"version": "8.55.0", "version": "8.55.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.55.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.55.0.tgz",
"integrity": "sha512-zRcVVPFUYWa3kNnjaZGXSu3xkKV1zXy8M4nO/pElzQhFweb7PPtluDLQtKArEOGmjXoRjnUZ29NjOiF0eCDkcQ==", "integrity": "sha512-zRcVVPFUYWa3kNnjaZGXSu3xkKV1zXy8M4nO/pElzQhFweb7PPtluDLQtKArEOGmjXoRjnUZ29NjOiF0eCDkcQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.55.0", "@typescript-eslint/tsconfig-utils": "^8.55.0",
@@ -774,6 +744,7 @@
"version": "8.55.0", "version": "8.55.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.55.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.55.0.tgz",
"integrity": "sha512-fVu5Omrd3jeqeQLiB9f1YsuK/iHFOwb04bCtY4BSCLgjNbOD33ZdV6KyEqplHr+IlpgT0QTZ/iJ+wT7hvTx49Q==", "integrity": "sha512-fVu5Omrd3jeqeQLiB9f1YsuK/iHFOwb04bCtY4BSCLgjNbOD33ZdV6KyEqplHr+IlpgT0QTZ/iJ+wT7hvTx49Q==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.55.0", "@typescript-eslint/types": "8.55.0",
@@ -791,6 +762,7 @@
"version": "8.55.0", "version": "8.55.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.55.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.55.0.tgz",
"integrity": "sha512-1R9cXqY7RQd7WuqSN47PK9EDpgFUK3VqdmbYrvWJZYDd0cavROGn+74ktWBlmJ13NXUQKlZ/iAEQHI/V0kKe0Q==", "integrity": "sha512-1R9cXqY7RQd7WuqSN47PK9EDpgFUK3VqdmbYrvWJZYDd0cavROGn+74ktWBlmJ13NXUQKlZ/iAEQHI/V0kKe0Q==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -807,6 +779,7 @@
"version": "8.55.0", "version": "8.55.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.55.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.55.0.tgz",
"integrity": "sha512-x1iH2unH4qAt6I37I2CGlsNs+B9WGxurP2uyZLRz6UJoZWDBx9cJL1xVN/FiOmHEONEg6RIufdvyT0TEYIgC5g==", "integrity": "sha512-x1iH2unH4qAt6I37I2CGlsNs+B9WGxurP2uyZLRz6UJoZWDBx9cJL1xVN/FiOmHEONEg6RIufdvyT0TEYIgC5g==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.55.0", "@typescript-eslint/types": "8.55.0",
@@ -831,6 +804,7 @@
"version": "8.55.0", "version": "8.55.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.55.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.55.0.tgz",
"integrity": "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==", "integrity": "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -844,6 +818,7 @@
"version": "8.55.0", "version": "8.55.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.55.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.55.0.tgz",
"integrity": "sha512-EwrH67bSWdx/3aRQhCoxDaHM+CrZjotc2UCCpEDVqfCE+7OjKAGWNY2HsCSTEVvWH2clYQK8pdeLp42EVs+xQw==", "integrity": "sha512-EwrH67bSWdx/3aRQhCoxDaHM+CrZjotc2UCCpEDVqfCE+7OjKAGWNY2HsCSTEVvWH2clYQK8pdeLp42EVs+xQw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/project-service": "8.55.0", "@typescript-eslint/project-service": "8.55.0",
@@ -871,6 +846,7 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
@@ -880,6 +856,7 @@
"version": "9.0.5", "version": "9.0.5",
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
@@ -895,6 +872,7 @@
"version": "8.55.0", "version": "8.55.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.55.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.55.0.tgz",
"integrity": "sha512-BqZEsnPGdYpgyEIkDC1BadNY8oMwckftxBT+C8W0g1iKPdeqKZBtTfnvcq0nf60u7MkjFO8RBvpRGZBPw4L2ow==", "integrity": "sha512-BqZEsnPGdYpgyEIkDC1BadNY8oMwckftxBT+C8W0g1iKPdeqKZBtTfnvcq0nf60u7MkjFO8RBvpRGZBPw4L2ow==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.9.1", "@eslint-community/eslint-utils": "^4.9.1",
@@ -918,6 +896,7 @@
"version": "8.55.0", "version": "8.55.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.55.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.55.0.tgz",
"integrity": "sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==", "integrity": "sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.55.0", "@typescript-eslint/types": "8.55.0",
@@ -935,6 +914,7 @@
"version": "8.15.0", "version": "8.15.0",
"resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.15.0.tgz", "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT", "license": "MIT",
"peer": true, "peer": true,
"bin": { "bin": {
@@ -948,6 +928,7 @@
"version": "5.3.2", "version": "5.3.2",
"resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"peerDependencies": { "peerDependencies": {
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
@@ -957,6 +938,7 @@
"version": "6.12.6", "version": "6.12.6",
"resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"fast-deep-equal": "^3.1.1", "fast-deep-equal": "^3.1.1",
@@ -973,6 +955,7 @@
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"color-convert": "^2.0.1" "color-convert": "^2.0.1"
@@ -988,18 +971,21 @@
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true,
"license": "Python-2.0" "license": "Python-2.0"
}, },
"node_modules/balanced-match": { "node_modules/balanced-match": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "1.1.12", "version": "1.1.12",
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.12.tgz", "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
@@ -1010,6 +996,7 @@
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=6" "node": ">=6"
@@ -1019,6 +1006,7 @@
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ansi-styles": "^4.1.0", "ansi-styles": "^4.1.0",
@@ -1035,6 +1023,7 @@
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"color-name": "~1.1.4" "color-name": "~1.1.4"
@@ -1047,18 +1036,21 @@
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/concat-map": { "node_modules/concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.6", "version": "7.0.6",
"resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz", "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"path-key": "^3.1.0", "path-key": "^3.1.0",
@@ -1073,6 +1065,7 @@
"version": "4.4.3", "version": "4.4.3",
"resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ms": "^2.1.3" "ms": "^2.1.3"
@@ -1090,6 +1083,7 @@
"version": "0.1.4", "version": "0.1.4",
"resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz", "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz",
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/esbuild": { "node_modules/esbuild": {
@@ -1137,6 +1131,7 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=10" "node": ">=10"
@@ -1149,6 +1144,7 @@
"version": "9.39.2", "version": "9.39.2",
"resolved": "https://registry.npmmirror.com/eslint/-/eslint-9.39.2.tgz", "resolved": "https://registry.npmmirror.com/eslint/-/eslint-9.39.2.tgz",
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
"dev": true,
"license": "MIT", "license": "MIT",
"peer": true, "peer": true,
"dependencies": { "dependencies": {
@@ -1209,6 +1205,7 @@
"version": "8.4.0", "version": "8.4.0",
"resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-8.4.0.tgz", "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-8.4.0.tgz",
"integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
"dev": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"esrecurse": "^4.3.0", "esrecurse": "^4.3.0",
@@ -1225,6 +1222,7 @@
"version": "4.2.1", "version": "4.2.1",
"resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1237,6 +1235,7 @@
"version": "0.17.0", "version": "0.17.0",
"resolved": "https://registry.npmmirror.com/@eslint/core/-/core-0.17.0.tgz", "resolved": "https://registry.npmmirror.com/@eslint/core/-/core-0.17.0.tgz",
"integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@types/json-schema": "^7.0.15" "@types/json-schema": "^7.0.15"
@@ -1249,6 +1248,7 @@
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmmirror.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", "resolved": "https://registry.npmmirror.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
"integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@eslint/core": "^0.17.0", "@eslint/core": "^0.17.0",
@@ -1262,6 +1262,7 @@
"version": "10.4.0", "version": "10.4.0",
"resolved": "https://registry.npmmirror.com/espree/-/espree-10.4.0.tgz", "resolved": "https://registry.npmmirror.com/espree/-/espree-10.4.0.tgz",
"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
"dev": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"acorn": "^8.15.0", "acorn": "^8.15.0",
@@ -1279,6 +1280,7 @@
"version": "1.7.0", "version": "1.7.0",
"resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.7.0.tgz", "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.7.0.tgz",
"integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
"dev": true,
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"estraverse": "^5.1.0" "estraverse": "^5.1.0"
@@ -1291,6 +1293,7 @@
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz",
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
"dev": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"estraverse": "^5.2.0" "estraverse": "^5.2.0"
@@ -1303,6 +1306,7 @@
"version": "5.3.0", "version": "5.3.0",
"resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"engines": { "engines": {
"node": ">=4.0" "node": ">=4.0"
@@ -1312,6 +1316,7 @@
"version": "2.0.3", "version": "2.0.3",
"resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
@@ -1321,24 +1326,28 @@
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/fast-json-stable-stringify": { "node_modules/fast-json-stable-stringify": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/fast-levenshtein": { "node_modules/fast-levenshtein": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/fdir": { "node_modules/fdir": {
"version": "6.5.0", "version": "6.5.0",
"resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=12.0.0" "node": ">=12.0.0"
@@ -1356,6 +1365,7 @@
"version": "8.0.0", "version": "8.0.0",
"resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
"integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"flat-cache": "^4.0.0" "flat-cache": "^4.0.0"
@@ -1368,6 +1378,7 @@
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz",
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"locate-path": "^6.0.0", "locate-path": "^6.0.0",
@@ -1384,6 +1395,7 @@
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-4.0.1.tgz", "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-4.0.1.tgz",
"integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"flatted": "^3.2.9", "flatted": "^3.2.9",
@@ -1397,12 +1409,14 @@
"version": "3.3.3", "version": "3.3.3",
"resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.3.3.tgz", "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.3.3.tgz",
"integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/glob-parent": { "node_modules/glob-parent": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"is-glob": "^4.0.3" "is-glob": "^4.0.3"
@@ -1427,6 +1441,7 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@@ -1436,6 +1451,7 @@
"version": "5.3.2", "version": "5.3.2",
"resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz", "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz",
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 4" "node": ">= 4"
@@ -1445,6 +1461,7 @@
"version": "3.3.1", "version": "3.3.1",
"resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.1.tgz", "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.1.tgz",
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"parent-module": "^1.0.0", "parent-module": "^1.0.0",
@@ -1461,6 +1478,7 @@
"version": "0.1.4", "version": "0.1.4",
"resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz",
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=0.8.19" "node": ">=0.8.19"
@@ -1470,6 +1488,7 @@
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
@@ -1479,6 +1498,7 @@
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"is-extglob": "^2.1.1" "is-extglob": "^2.1.1"
@@ -1491,6 +1511,7 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/jiti": { "node_modules/jiti": {
@@ -1517,6 +1538,7 @@
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.1.tgz", "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"argparse": "^2.0.1" "argparse": "^2.0.1"
@@ -1529,24 +1551,28 @@
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz", "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz",
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/json-schema-traverse": { "node_modules/json-schema-traverse": {
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/json-stable-stringify-without-jsonify": { "node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/keyv": { "node_modules/keyv": {
"version": "4.5.4", "version": "4.5.4",
"resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"json-buffer": "3.0.1" "json-buffer": "3.0.1"
@@ -1556,6 +1582,7 @@
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz",
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"prelude-ls": "^1.2.1", "prelude-ls": "^1.2.1",
@@ -1569,6 +1596,7 @@
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"p-locate": "^5.0.0" "p-locate": "^5.0.0"
@@ -1584,12 +1612,14 @@
"version": "4.6.2", "version": "4.6.2",
"resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz", "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
@@ -1602,18 +1632,21 @@
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/natural-compare": { "node_modules/natural-compare": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz",
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/optionator": { "node_modules/optionator": {
"version": "0.9.4", "version": "0.9.4",
"resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz", "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz",
"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"deep-is": "^0.1.3", "deep-is": "^0.1.3",
@@ -1631,6 +1664,7 @@
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"yocto-queue": "^0.1.0" "yocto-queue": "^0.1.0"
@@ -1646,6 +1680,7 @@
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"p-limit": "^3.0.2" "p-limit": "^3.0.2"
@@ -1661,6 +1696,7 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"callsites": "^3.0.0" "callsites": "^3.0.0"
@@ -1673,6 +1709,7 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@@ -1682,6 +1719,7 @@
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@@ -1691,6 +1729,7 @@
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT", "license": "MIT",
"peer": true, "peer": true,
"engines": { "engines": {
@@ -1704,6 +1743,7 @@
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz",
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 0.8.0" "node": ">= 0.8.0"
@@ -1713,6 +1753,7 @@
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=6" "node": ">=6"
@@ -1722,6 +1763,7 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=4" "node": ">=4"
@@ -1731,6 +1773,7 @@
"version": "7.7.4", "version": "7.7.4",
"resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.4.tgz", "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.4.tgz",
"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
"dev": true,
"license": "ISC", "license": "ISC",
"bin": { "bin": {
"semver": "bin/semver.js" "semver": "bin/semver.js"
@@ -1743,6 +1786,7 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"shebang-regex": "^3.0.0" "shebang-regex": "^3.0.0"
@@ -1755,6 +1799,7 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@@ -1764,6 +1809,7 @@
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@@ -1776,6 +1822,7 @@
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"has-flag": "^4.0.0" "has-flag": "^4.0.0"
@@ -1788,6 +1835,7 @@
"version": "0.2.15", "version": "0.2.15",
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz", "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz",
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"fdir": "^6.5.0", "fdir": "^6.5.0",
@@ -1804,6 +1852,7 @@
"version": "2.4.0", "version": "2.4.0",
"resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-2.4.0.tgz", "resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-2.4.0.tgz",
"integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18.12" "node": ">=18.12"
@@ -1816,6 +1865,7 @@
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz", "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz",
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"prelude-ls": "^1.2.1" "prelude-ls": "^1.2.1"
@@ -1828,6 +1878,7 @@
"version": "5.9.3", "version": "5.9.3",
"resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz", "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true, "peer": true,
"bin": { "bin": {
@@ -1842,6 +1893,7 @@
"version": "8.55.0", "version": "8.55.0",
"resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.55.0.tgz", "resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.55.0.tgz",
"integrity": "sha512-HE4wj+r5lmDVS9gdaN0/+iqNvPZwGfnJ5lZuz7s5vLlg9ODw0bIiiETaios9LvFI1U94/VBXGm3CB2Y5cNFMpw==", "integrity": "sha512-HE4wj+r5lmDVS9gdaN0/+iqNvPZwGfnJ5lZuz7s5vLlg9ODw0bIiiETaios9LvFI1U94/VBXGm3CB2Y5cNFMpw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/eslint-plugin": "8.55.0", "@typescript-eslint/eslint-plugin": "8.55.0",
@@ -1865,6 +1917,7 @@
"version": "4.4.1", "version": "4.4.1",
"resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"dev": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"punycode": "^2.1.0" "punycode": "^2.1.0"
@@ -1874,6 +1927,7 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"isexe": "^2.0.0" "isexe": "^2.0.0"
@@ -1889,6 +1943,7 @@
"version": "1.2.5", "version": "1.2.5",
"resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz", "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz",
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
@@ -1898,6 +1953,7 @@
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz", "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=10" "node": ">=10"

View File

@@ -10,12 +10,13 @@
}, },
"devDependencies": { "devDependencies": {
"esbuild": "^0.24.2", "esbuild": "^0.24.2",
"typescript": "^5.7.2" "eslint": "^9.39.2",
"typescript": "^5.7.2",
"typescript-eslint": "^8.55.0",
"jiti": "^2.6.1"
}, },
"dependencies": { "dependencies": {
"eslint": "^9.39.2",
"globals": "^17.3.0", "globals": "^17.3.0",
"js-sdsl": "^4.4.2", "js-sdsl": "^4.4.2"
"typescript-eslint": "^8.55.0"
} }
} }

View File

@@ -1,6 +1,5 @@
import type { NixRuntime } from ".."; import type { NixRuntime } from "..";
import type { builtins } from "../builtins"; import type { builtins } from "../builtins";
import { JsonValue } from "../builtins/conversion";
import type { FetchGitResult, FetchTarballResult, FetchUrlResult } from "../builtins/io"; import type { FetchGitResult, FetchTarballResult, FetchUrlResult } from "../builtins/io";
import type { import type {
assert, assert,

View File

@@ -188,7 +188,6 @@ impl<Ctx: CodegenContext> Compile<Ctx> for rnix::TextRange {
} }
pub(crate) trait CodegenContext { pub(crate) trait CodegenContext {
fn get_ir(&self, id: ExprId) -> &Ir;
fn get_sym(&self, id: SymId) -> Symbol<'_>; fn get_sym(&self, id: SymId) -> Symbol<'_>;
fn get_current_dir(&self) -> &Path; fn get_current_dir(&self) -> &Path;
fn get_store_dir(&self) -> &str; fn get_store_dir(&self) -> &str;
@@ -196,19 +195,13 @@ pub(crate) trait CodegenContext {
fn register_span(&self, range: rnix::TextRange) -> usize; fn register_span(&self, range: rnix::TextRange) -> usize;
} }
impl<Ctx: CodegenContext> Compile<Ctx> for ExprId {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
ctx.get_ir(*self).compile(ctx, buf);
}
}
impl<Ctx: CodegenContext> Compile<Ctx> for Symbol<'_> { impl<Ctx: CodegenContext> Compile<Ctx> for Symbol<'_> {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) { fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
quoted(self).compile(ctx, buf); quoted(self).compile(ctx, buf);
} }
} }
impl<Ctx: CodegenContext> Compile<Ctx> for Ir { impl<Ctx: CodegenContext> Compile<Ctx> for Ir<'_> {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) { fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
match self { match self {
Ir::Int(int) => { Ir::Int(int) => {
@@ -224,11 +217,11 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Ir {
code!(buf, ctx; "null"); code!(buf, ctx; "null");
} }
Ir::Str(s) => { Ir::Str(s) => {
code!(buf, ctx; quoted(&s.val)); code!(buf, ctx; quoted(&s.inner));
} }
Ir::Path(p) => { Ir::Path(p) => {
// Nix.resolvePath // Nix.resolvePath
code!(buf, ctx; "$r(_d," ctx.get_ir(p.expr) ")"); code!(buf, ctx; "$r(_d," p.expr ")");
} }
Ir::If(x) => x.compile(ctx, buf), Ir::If(x) => x.compile(ctx, buf),
Ir::BinOp(x) => x.compile(ctx, buf), Ir::BinOp(x) => x.compile(ctx, buf),
@@ -265,14 +258,12 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Ir {
ref assertion_raw, ref assertion_raw,
span: assert_span, span: assert_span,
}) => { }) => {
let assertion = ctx.get_ir(assertion);
// Nix.assert // Nix.assert
code!(buf, ctx; code!(buf, ctx;
"$a(" "$a("
assertion assertion
"," ","
ctx.get_ir(expr) expr
"," ","
quoted(assertion_raw) quoted(assertion_raw)
"," ","
@@ -316,7 +307,7 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Ir {
} }
} }
impl<Ctx: CodegenContext> Compile<Ctx> for If { impl<Ctx: CodegenContext> Compile<Ctx> for If<'_> {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) { fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
let &If { let &If {
cond, cond,
@@ -324,19 +315,18 @@ impl<Ctx: CodegenContext> Compile<Ctx> for If {
alter, alter,
span: _, span: _,
} = self; } = self;
let cond = ctx.get_ir(cond);
// Nix.forceBool // Nix.forceBool
code!(buf, ctx; "$fb(" cond ")?(" consq "):(" alter ")"); code!(buf, ctx; "$fb(" cond ")?(" consq "):(" alter ")");
} }
} }
impl<Ctx: CodegenContext> Compile<Ctx> for BinOp { impl<Ctx: CodegenContext> Compile<Ctx> for BinOp<'_> {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) { fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
use BinOpKind::*; use BinOpKind::*;
let lhs = ctx.get_ir(self.lhs); let lhs = self.lhs;
let rhs = ctx.get_ir(self.rhs); let rhs = self.rhs;
match self.kind { match self.kind {
Add | Sub | Mul | Div | Eq | Neq | Lt | Gt | Leq | Geq | Con | Upd => { Add | Sub | Mul | Div | Eq | Neq | Lt | Gt | Leq | Geq | Con | Upd => {
@@ -389,24 +379,30 @@ impl<Ctx: CodegenContext> Compile<Ctx> for BinOp {
} }
} }
impl<Ctx: CodegenContext> Compile<Ctx> for UnOp { impl<Ctx: CodegenContext> Compile<Ctx> for UnOp<'_> {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) { fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
use UnOpKind::*; use UnOpKind::*;
let rhs = ctx.get_ir(self.rhs); let rhs = self.rhs;
match self.kind { match self.kind {
Neg => { Neg => {
code!(buf, ctx; "$os(0n," rhs ")"); code!(buf, ctx; "$os(0n," rhs ")");
} }
Not => { Not => {
code!(buf, ctx; "!$fb(" ctx.get_ir(self.rhs) ")"); code!(buf, ctx; "!$fb(" rhs ")");
} }
} }
} }
} }
impl<Ctx: CodegenContext> Compile<Ctx> for Func { impl<Ctx: CodegenContext> Compile<Ctx> for Func<'_> {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) { fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
let id = ctx.get_ir(self.arg).as_ref().unwrap_arg().inner.0; let Ir::Arg(Arg {
inner: ArgId(id), ..
}) = self.arg
else {
// TODO:
unreachable!()
};
let has_thunks = !self.thunks.is_empty(); let has_thunks = !self.thunks.is_empty();
@@ -450,13 +446,13 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Func {
} }
} }
impl<Ctx: CodegenContext> Compile<Ctx> for Call { impl<Ctx: CodegenContext> Compile<Ctx> for Call<'_> {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) { fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
code!(buf, ctx; code!(buf, ctx;
"$c(" "$c("
ctx.get_ir(self.func) self.func
"," ","
ctx.get_ir(self.arg) self.arg
"," ","
self.span self.span
")" ")"
@@ -464,7 +460,7 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Call {
} }
} }
impl<Ctx: CodegenContext> Compile<Ctx> for [(ExprId, ExprId)] { impl<'ir, Ctx: CodegenContext> Compile<Ctx> for [(ThunkId, IrRef<'ir>)] {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) { fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
if self.is_empty() { if self.is_empty() {
return; return;
@@ -474,28 +470,27 @@ impl<Ctx: CodegenContext> Compile<Ctx> for [(ExprId, ExprId)] {
buf, ctx; buf, ctx;
"const " "const "
joined(self.iter(), ",", |ctx: &Ctx, buf, &(slot, inner)| { joined(self.iter(), ",", |ctx: &Ctx, buf, &(slot, inner)| {
code!(buf, ctx; "e" slot.0 "=$t(()=>(" ctx.get_ir(inner) ")," "'e" slot.0 "')"); code!(buf, ctx; "e" slot.0 "=$t(()=>(" inner ")," "'e" slot.0 "')");
}) })
";" ";"
); );
} }
} }
impl<Ctx: CodegenContext> Compile<Ctx> for TopLevel { impl<Ctx: CodegenContext> Compile<Ctx> for TopLevel<'_> {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) { fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
if self.thunks.is_empty() { if self.thunks.is_empty() {
ctx.get_ir(self.body).compile(ctx, buf); self.body.compile(ctx, buf);
} else { } else {
let body = ctx.get_ir(self.body); code!(buf, ctx; "(()=>{" self.thunks "return " self.body "})()");
code!(buf, ctx; "(()=>{" self.thunks "return " body "})()");
} }
} }
} }
impl<Ctx: CodegenContext> Compile<Ctx> for WithExpr { impl<Ctx: CodegenContext> Compile<Ctx> for WithExpr<'_> {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) { fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
let namespace = ctx.get_ir(self.namespace); let namespace = self.namespace;
let body = ctx.get_ir(self.body); let body = self.body;
let has_thunks = !self.thunks.is_empty(); let has_thunks = !self.thunks.is_empty();
if has_thunks { if has_thunks {
code!(buf, ctx; "((_w)=>{" self.thunks "return " body "})({env:" namespace ",last:_w})"); code!(buf, ctx; "((_w)=>{" self.thunks "return " body "})({env:" namespace ",last:_w})");
@@ -505,21 +500,21 @@ impl<Ctx: CodegenContext> Compile<Ctx> for WithExpr {
} }
} }
impl<Ctx: CodegenContext> Compile<Ctx> for Select { impl<Ctx: CodegenContext> Compile<Ctx> for Select<'_> {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) { fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
if let Some(default) = self.default { if let Some(default) = self.default {
code!(buf, ctx; code!(buf, ctx;
"$sd(" "$sd("
ctx.get_ir(self.expr) self.expr
",[" ",["
joined(self.attrpath.iter(), ",", |ctx: &Ctx, buf, attr| { joined(self.attrpath.iter(), ",", |ctx: &Ctx, buf, attr| {
match attr { match attr {
Attr::Str(sym, _) => code!(buf, ctx; ctx.get_sym(*sym)), Attr::Str(sym, _) => code!(buf, ctx; ctx.get_sym(*sym)),
Attr::Dynamic(expr_id, _) => code!(buf, ctx; ctx.get_ir(*expr_id)), Attr::Dynamic(expr_id, _) => code!(buf, ctx; *expr_id),
} }
}) })
"]," "],"
ctx.get_ir(default) default
"," ","
self.span self.span
")" ")"
@@ -527,12 +522,12 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Select {
} else { } else {
code!(buf, ctx; code!(buf, ctx;
"$s(" "$s("
ctx.get_ir(self.expr) self.expr
",[" ",["
joined(self.attrpath.iter(), ",", |ctx: &Ctx, buf, attr| { joined(self.attrpath.iter(), ",", |ctx: &Ctx, buf, attr| {
match attr { match attr {
Attr::Str(sym, _) => code!(buf, ctx; ctx.get_sym(*sym)), Attr::Str(sym, _) => code!(buf, ctx; ctx.get_sym(*sym)),
Attr::Dynamic(expr_id, _) => code!(buf, ctx; ctx.get_ir(*expr_id)), Attr::Dynamic(expr, _) => code!(buf, ctx; expr),
} }
}) })
"]," "],"
@@ -543,15 +538,13 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Select {
} }
} }
impl<Ctx: CodegenContext> Compile<Ctx> for AttrSet { impl<Ctx: CodegenContext> Compile<Ctx> for AttrSet<'_> {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) { fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
if !self.dyns.is_empty() { if !self.dyns.is_empty() {
code!(buf, ctx; code!(buf, ctx;
"$ma(new Map([" "$ma(new Map(["
joined(self.stcs.iter(), ",", |ctx: &Ctx, buf, (&sym, &(expr, _))| { joined(self.stcs.iter(), ",", |ctx: &Ctx, buf, (&sym, &(val, _))| {
let key = ctx.get_sym(sym); let key = ctx.get_sym(sym);
let val = ctx.get_ir(expr);
code!( code!(
buf, ctx; buf, ctx;
"[" key "," val "]" "[" key "," val "]"
@@ -563,11 +556,10 @@ impl<Ctx: CodegenContext> Compile<Ctx> for AttrSet {
}) })
"]),{dynKeys:[" "]),{dynKeys:["
joined(self.dyns.iter(), ",", |ctx: &Ctx, buf, (key, _, _)| { joined(self.dyns.iter(), ",", |ctx: &Ctx, buf, (key, _, _)| {
code!(buf, ctx; ctx.get_ir(*key)); code!(buf, ctx; key);
}) })
"],dynVals:[" "],dynVals:["
joined(self.dyns.iter(), ",", |ctx: &Ctx, buf, (_, val, _)| { joined(self.dyns.iter(), ",", |ctx: &Ctx, buf, (_, val, _)| {
let val = ctx.get_ir(*val);
code!(buf, ctx; val); code!(buf, ctx; val);
}) })
"],dynSpans:[" "],dynSpans:["
@@ -579,10 +571,8 @@ impl<Ctx: CodegenContext> Compile<Ctx> for AttrSet {
} else if !self.stcs.is_empty() { } else if !self.stcs.is_empty() {
code!(buf, ctx; code!(buf, ctx;
"$ma(new Map([" "$ma(new Map(["
joined(self.stcs.iter(), ",", |ctx: &Ctx, buf, (&sym, &(expr, _))| { joined(self.stcs.iter(), ",", |ctx: &Ctx, buf, (&sym, &(val, _))| {
let key = ctx.get_sym(sym); let key = ctx.get_sym(sym);
let val = ctx.get_ir(expr);
code!( code!(
buf, ctx; buf, ctx;
"[" key "," val "]" "[" key "," val "]"
@@ -600,12 +590,11 @@ impl<Ctx: CodegenContext> Compile<Ctx> for AttrSet {
} }
} }
impl<Ctx: CodegenContext> Compile<Ctx> for List { impl<Ctx: CodegenContext> Compile<Ctx> for List<'_> {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) { fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
code!(buf, ctx; code!(buf, ctx;
"[" "["
joined(self.items.iter(), ",", |ctx: &Ctx, buf, item| { joined(self.items.iter(), ",", |ctx: &Ctx, buf, item| {
let item = ctx.get_ir(*item);
code!(buf, ctx; item); code!(buf, ctx; item);
}) })
"]" "]"
@@ -613,12 +602,11 @@ impl<Ctx: CodegenContext> Compile<Ctx> for List {
} }
} }
impl<Ctx: CodegenContext> Compile<Ctx> for ConcatStrings { impl<Ctx: CodegenContext> Compile<Ctx> for ConcatStrings<'_> {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) { fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
code!(buf, ctx; code!(buf, ctx;
"$cs([" "$cs(["
joined(self.parts.iter(), ",", |ctx: &Ctx, buf, part| { joined(self.parts.iter(), ",", |ctx: &Ctx, buf, part| {
let part = ctx.get_ir(*part);
code!(buf, ctx; part); code!(buf, ctx; part);
}) })
"]," self.force_string ")" "]," self.force_string ")"
@@ -626,16 +614,16 @@ impl<Ctx: CodegenContext> Compile<Ctx> for ConcatStrings {
} }
} }
impl<Ctx: CodegenContext> Compile<Ctx> for HasAttr { impl<Ctx: CodegenContext> Compile<Ctx> for HasAttr<'_> {
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) { fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
code!(buf, ctx; code!(buf, ctx;
"$h(" "$h("
ctx.get_ir(self.lhs) self.lhs
",[" ",["
joined(self.rhs.iter(), ",", |ctx: &Ctx, buf, attr| { joined(self.rhs.iter(), ",", |ctx: &Ctx, buf, attr| {
match attr { match attr {
Attr::Str(sym, _) => code!(buf, ctx; ctx.get_sym(*sym)), Attr::Str(sym, _) => code!(buf, ctx; ctx.get_sym(*sym)),
Attr::Dynamic(expr_id, _) => code!(buf, ctx; ctx.get_ir(*expr_id)), Attr::Dynamic(expr, _) => code!(buf, ctx; expr),
} }
}) })
"])" "])"

View File

@@ -1,7 +1,7 @@
use std::cell::UnsafeCell; use std::cell::UnsafeCell;
use std::path::Path; use std::path::Path;
use std::ptr::NonNull;
use bumpalo::Bump;
use hashbrown::{HashMap, HashSet}; use hashbrown::{HashMap, HashSet};
use rnix::TextRange; use rnix::TextRange;
use string_interner::DefaultStringInterner; use string_interner::DefaultStringInterner;
@@ -10,8 +10,8 @@ use crate::codegen::{CodegenContext, compile, compile_scoped};
use crate::downgrade::*; use crate::downgrade::*;
use crate::error::{Error, Result, Source}; use crate::error::{Error, Result, Source};
use crate::ir::{ use crate::ir::{
Arg, ArgId, Bool, Builtin, ExprId, Ir, Null, ReplBinding, ScopedImportBinding, SymId, Thunk, Arg, ArgId, Bool, Builtin, Ir, IrRef, Null, ReplBinding, ScopedImportBinding, SymId, Thunk,
ToIr as _, WithLookup, ThunkId, ToIr as _, WithLookup,
}; };
#[cfg(feature = "inspector")] #[cfg(feature = "inspector")]
use crate::runtime::inspector::InspectorServer; use crate::runtime::inspector::InspectorServer;
@@ -183,12 +183,23 @@ impl Context {
} }
pub(crate) struct Ctx { pub(crate) struct Ctx {
irs: Vec<Ir>,
symbols: DefaultStringInterner, symbols: DefaultStringInterner,
global: NonNull<HashMap<SymId, ExprId>>, global: HashMap<SymId, Ir<'static>>,
sources: Vec<Source>, sources: Vec<Source>,
store: DaemonStore, store: DaemonStore,
spans: UnsafeCell<Vec<(usize, TextRange)>>, spans: UnsafeCell<Vec<(usize, TextRange)>>,
thunk_count: usize,
}
struct OwnedIr {
_bump: Bump,
ir: &'static Ir<'static>,
}
impl OwnedIr {
fn as_ref<'ir>(&'ir self) -> IrRef<'ir> {
self.ir
}
} }
impl Ctx { impl Ctx {
@@ -196,19 +207,15 @@ impl Ctx {
use crate::ir::{Builtins, ToIr as _}; use crate::ir::{Builtins, ToIr as _};
let mut symbols = DefaultStringInterner::new(); let mut symbols = DefaultStringInterner::new();
let mut irs = Vec::new();
let mut global = HashMap::new(); let mut global = HashMap::new();
let builtins_sym = symbols.get_or_intern("builtins");
irs.push( global.insert(
builtins_sym,
Builtins { Builtins {
span: rnix::TextRange::default(), span: TextRange::default(),
} }
.to_ir(), .to_ir(),
); );
let builtins_expr = ExprId(0);
let builtins_sym = symbols.get_or_intern("builtins");
global.insert(builtins_sym, builtins_expr);
let free_globals = [ let free_globals = [
"abort", "abort",
@@ -258,22 +265,17 @@ impl Ctx {
]; ];
for name in free_globals { for name in free_globals {
let name_sym = symbols.get_or_intern(name); let name = symbols.get_or_intern(name);
let id = ExprId(irs.len()); let value = Builtin {
irs.push( inner: name,
Builtin { span: rnix::TextRange::default(),
inner: name_sym, }
span: rnix::TextRange::default(), .to_ir();
} global.insert(name, value);
.to_ir(),
);
global.insert(name_sym, id);
} }
for (name, value) in consts { for (name, value) in consts {
let name_sym = symbols.get_or_intern(name); let name = symbols.get_or_intern(name);
let id = ExprId(irs.len()); global.insert(name, value);
irs.push(value);
global.insert(name_sym, id);
} }
let config = StoreConfig::from_env(); let config = StoreConfig::from_env();
@@ -281,17 +283,28 @@ impl Ctx {
Ok(Self { Ok(Self {
symbols, symbols,
irs, global,
global: unsafe { NonNull::new_unchecked(Box::leak(Box::new(global))) },
sources: Vec::new(), sources: Vec::new(),
store, store,
spans: UnsafeCell::new(Vec::new()), spans: UnsafeCell::new(Vec::new()),
thunk_count: 0,
}) })
} }
fn downgrade_ctx<'a>(&'a mut self, extra_scope: Option<Scope<'a>>) -> DowngradeCtx<'a> { fn downgrade_ctx<'ctx, 'ir>(
let global_ref = unsafe { self.global.as_ref() }; &'ctx mut self,
DowngradeCtx::new(self, global_ref, extra_scope) bump: &'ir Bump,
extra_scope: Option<Scope<'ctx, 'ir>>,
) -> DowngradeCtx<'ctx, 'ir> {
let source = self.get_current_source();
DowngradeCtx::new(
bump,
&mut self.symbols,
&self.global,
extra_scope,
&mut self.thunk_count,
source,
)
} }
pub(crate) fn get_current_dir(&self) -> &Path { pub(crate) fn get_current_dir(&self) -> &Path {
@@ -313,7 +326,11 @@ impl Ctx {
self.sources.get(id).expect("source not found").clone() self.sources.get(id).expect("source not found").clone()
} }
fn downgrade<'a>(&mut self, source: Source, extra_scope: Option<Scope<'a>>) -> Result<ExprId> { fn downgrade<'ctx>(
&'ctx mut self,
source: Source,
extra_scope: Option<Scope<'ctx, 'static>>,
) -> Result<OwnedIr> {
tracing::debug!("Parsing Nix expression"); tracing::debug!("Parsing Nix expression");
self.sources.push(source.clone()); self.sources.push(source.clone());
@@ -326,13 +343,22 @@ impl Ctx {
.tree() .tree()
.expr() .expr()
.ok_or_else(|| Error::parse_error("unexpected EOF".into()))?; .ok_or_else(|| Error::parse_error("unexpected EOF".into()))?;
self.downgrade_ctx(extra_scope).downgrade(expr) let bump = Bump::new();
let ir = self
.downgrade_ctx(&bump, extra_scope)
.downgrade_toplevel(expr)?;
let ir = unsafe { std::mem::transmute::<IrRef<'_>, IrRef<'static>>(ir) };
Ok(OwnedIr { _bump: bump, ir })
} }
fn compile<'a>(&'a mut self, source: Source, extra_scope: Option<Scope<'a>>) -> Result<String> { fn compile<'ctx>(
&'ctx mut self,
source: Source,
extra_scope: Option<Scope<'ctx, 'static>>,
) -> Result<String> {
let root = self.downgrade(source, extra_scope)?; let root = self.downgrade(source, extra_scope)?;
tracing::debug!("Generating JavaScript code"); tracing::debug!("Generating JavaScript code");
let code = compile(self.get_ir(root), self); let code = compile(root.as_ref(), self);
tracing::debug!("Generated code: {}", &code); tracing::debug!("Generated code: {}", &code);
Ok(code) Ok(code)
} }
@@ -346,16 +372,13 @@ impl Ctx {
); );
let root = self.downgrade(source, Some(scope))?; let root = self.downgrade(source, Some(scope))?;
tracing::debug!("Generating JavaScript code for scoped import"); tracing::debug!("Generating JavaScript code for scoped import");
let code = compile_scoped(self.get_ir(root), self); let code = compile_scoped(root.as_ref(), self);
tracing::debug!("Generated scoped code: {}", &code); tracing::debug!("Generated scoped code: {}", &code);
Ok(code) Ok(code)
} }
} }
impl CodegenContext for Ctx { impl CodegenContext for Ctx {
fn get_ir(&self, id: ExprId) -> &Ir {
self.irs.get(id.0).expect("ExprId out of bounds")
}
fn get_sym(&self, id: SymId) -> Symbol<'_> { fn get_sym(&self, id: SymId) -> Symbol<'_> {
self.symbols self.symbols
.resolve(id) .resolve(id)
@@ -401,126 +424,129 @@ impl RuntimeContext for Ctx {
fn get_store(&self) -> &DaemonStore { fn get_store(&self) -> &DaemonStore {
&self.store &self.store
} }
fn get_span(&self, id: usize) -> (usize, rnix::TextRange) { fn get_span(&self, id: usize) -> (usize, TextRange) {
let spans = unsafe { &*self.spans.get() }; let spans = unsafe { &*self.spans.get() };
spans[id] spans[id]
} }
} }
enum Scope<'ctx> { enum Scope<'ctx, 'ir> {
Global(&'ctx HashMap<SymId, ExprId>), Global(&'ctx HashMap<SymId, Ir<'static>>),
Repl(&'ctx HashSet<SymId>), Repl(&'ctx HashSet<SymId>),
ScopedImport(HashSet<SymId>), ScopedImport(HashSet<SymId>),
Let(HashMap<SymId, ExprId>), Let(HashMap<SymId, ThunkId>),
Param(SymId, ExprId), Param(SymId, IrRef<'ir>),
} }
struct ScopeGuard<'a, 'ctx> { struct ScopeGuard<'a, 'ctx, 'ir> {
ctx: &'a mut DowngradeCtx<'ctx>, ctx: &'a mut DowngradeCtx<'ctx, 'ir>,
} }
impl<'a, 'ctx> Drop for ScopeGuard<'a, 'ctx> { impl Drop for ScopeGuard<'_, '_, '_> {
fn drop(&mut self) { fn drop(&mut self) {
self.ctx.scopes.pop(); self.ctx.scopes.pop();
} }
} }
impl<'a, 'ctx> ScopeGuard<'a, 'ctx> { impl<'ir, 'ctx> ScopeGuard<'_, 'ctx, 'ir> {
fn as_ctx(&mut self) -> &mut DowngradeCtx<'ctx> { fn as_ctx(&mut self) -> &mut DowngradeCtx<'ctx, 'ir> {
self.ctx self.ctx
} }
} }
pub struct DowngradeCtx<'ctx> { pub struct DowngradeCtx<'ctx, 'ir> {
ctx: &'ctx mut Ctx, bump: &'ir Bump,
irs: Vec<Ir>, symbols: &'ctx mut DefaultStringInterner,
scopes: Vec<Scope<'ctx>>, source: Source,
scopes: Vec<Scope<'ctx, 'ir>>,
with_scope_count: usize, with_scope_count: usize,
arg_id: usize, arg_count: usize,
thunk_scopes: Vec<Vec<(ExprId, ExprId)>>, thunk_count: &'ctx mut usize,
thunk_scopes: Vec<bumpalo::collections::Vec<'ir, (ThunkId, IrRef<'ir>)>>,
} }
impl<'ctx> DowngradeCtx<'ctx> { fn should_thunk(ir: IrRef<'_>) -> bool {
fn new( !matches!(
ctx: &'ctx mut Ctx, ir,
global: &'ctx HashMap<SymId, ExprId>, Ir::Builtin(_)
extra_scope: Option<Scope<'ctx>>,
) -> Self {
Self {
scopes: std::iter::once(Scope::Global(global))
.chain(extra_scope)
.collect(),
irs: vec![],
arg_id: 0,
with_scope_count: 0,
thunk_scopes: vec![Vec::new()],
ctx,
}
}
}
impl DowngradeContext for DowngradeCtx<'_> {
fn new_expr(&mut self, expr: Ir) -> ExprId {
self.irs.push(expr);
ExprId(self.ctx.irs.len() + self.irs.len() - 1)
}
fn new_arg(&mut self, span: TextRange) -> ExprId {
self.irs.push(
Arg {
inner: ArgId(self.arg_id),
span,
}
.to_ir(),
);
self.arg_id += 1;
ExprId(self.ctx.irs.len() + self.irs.len() - 1)
}
fn get_ir(&self, id: ExprId) -> &Ir {
if id.0 < self.ctx.irs.len() {
self.ctx.irs.get(id.0).expect("unreachable")
} else {
self.irs
.get(id.0 - self.ctx.irs.len())
.expect("ExprId out of bounds")
}
}
fn maybe_thunk(&mut self, id: ExprId) -> ExprId {
let ir = self.get_ir(id);
match ir {
Ir::Builtin(_)
| Ir::Builtins(_) | Ir::Builtins(_)
| Ir::Int(_) | Ir::Int(_)
| Ir::Float(_) | Ir::Float(_)
| Ir::Bool(_) | Ir::Bool(_)
| Ir::Null(_) | Ir::Null(_)
| Ir::Str(_) | Ir::Str(_)
| Ir::Thunk(_) => id, | Ir::Thunk(_)
_ => { )
let span = ir.span(); }
let slot = self.reserve_slots(1).next().expect("reserve_slots failed");
self.replace_ir(slot, Thunk { inner: slot, span }.to_ir()); impl<'ctx, 'ir> DowngradeCtx<'ctx, 'ir> {
self.register_thunk(slot, id); fn new(
slot bump: &'ir Bump,
symbols: &'ctx mut DefaultStringInterner,
global: &'ctx HashMap<SymId, Ir<'static>>,
extra_scope: Option<Scope<'ctx, 'ir>>,
thunk_count: &'ctx mut usize,
source: Source,
) -> Self {
Self {
bump,
symbols,
source,
scopes: std::iter::once(Scope::Global(global))
.chain(extra_scope)
.collect(),
thunk_count,
arg_count: 0,
with_scope_count: 0,
thunk_scopes: vec![bumpalo::collections::Vec::new_in(bump)],
}
}
}
impl<'ctx: 'ir, 'ir> DowngradeContext<'ir> for DowngradeCtx<'ctx, 'ir> {
fn new_expr(&self, expr: Ir<'ir>) -> IrRef<'ir> {
self.bump.alloc(expr)
}
fn new_arg(&mut self, span: TextRange) -> IrRef<'ir> {
self.arg_count += 1;
self.bump.alloc(
Arg {
inner: ArgId(self.arg_count - 1),
span,
} }
.to_ir(),
)
}
fn maybe_thunk(&mut self, ir: IrRef<'ir>) -> IrRef<'ir> {
if should_thunk(ir) {
let span = ir.span();
let id = ThunkId(*self.thunk_count);
*self.thunk_count += 1;
self.thunk_scopes
.last_mut()
.expect("no active thunk scope")
.push((id, ir));
self.new_expr(Thunk { inner: id, span }.to_ir())
} else {
ir
} }
} }
fn new_sym(&mut self, sym: String) -> SymId { fn new_sym(&mut self, sym: String) -> SymId {
self.ctx.symbols.get_or_intern(sym) self.symbols.get_or_intern(sym)
} }
fn get_sym(&self, id: SymId) -> Symbol<'_> { fn get_sym(&self, id: SymId) -> Symbol<'_> {
self.ctx.get_sym(id) self.symbols.resolve(id).expect("no symbol found").into()
} }
fn lookup(&mut self, sym: SymId, span: TextRange) -> Result<ExprId> { fn lookup(&self, sym: SymId, span: TextRange) -> Result<IrRef<'ir>> {
for scope in self.scopes.iter().rev() { for scope in self.scopes.iter().rev() {
match scope { match scope {
&Scope::Global(global_scope) => { &Scope::Global(global_scope) => {
if let Some(&expr) = global_scope.get(&sym) { if let Some(expr) = global_scope.get(&sym) {
return Ok(expr); return Ok(expr);
} }
} }
@@ -558,49 +584,32 @@ impl DowngradeContext for DowngradeCtx<'_> {
} }
} }
fn replace_ir(&mut self, id: ExprId, expr: Ir) {
let local_id = id.0 - self.ctx.irs.len();
*self.irs.get_mut(local_id).expect("ExprId out of bounds") = expr;
}
fn get_current_source(&self) -> Source { fn get_current_source(&self) -> Source {
self.ctx.get_current_source() self.source.clone()
} }
#[allow(refining_impl_trait)] fn with_let_scope<F, R>(&mut self, keys: &[SymId], f: F) -> Result<R>
fn reserve_slots(&mut self, slots: usize) -> impl Iterator<Item = ExprId> + Clone + use<> {
let start = self.ctx.irs.len() + self.irs.len();
let range = (start..start + slots).map(ExprId);
let span = rnix::TextRange::default();
// Fill reserved slots with placeholder value
self.irs.extend(
range
.clone()
.map(|slot| Thunk { inner: slot, span }.to_ir()),
);
range
}
fn downgrade(mut self, root: rnix::ast::Expr) -> Result<ExprId> {
use crate::ir::TopLevel;
let body = root.downgrade(&mut self)?;
let thunks = self.thunk_scopes.pop().expect("no thunk scope left???");
let span = self.get_ir(body).span();
let top_level = self.new_expr(TopLevel { body, thunks, span }.to_ir());
self.ctx.irs.extend(self.irs);
Ok(top_level)
}
fn with_let_scope<F, R>(&mut self, bindings: HashMap<SymId, ExprId>, f: F) -> R
where where
F: FnOnce(&mut Self) -> R, F: FnOnce(&mut Self) -> Result<(bumpalo::collections::Vec<'ir, IrRef<'ir>>, R)>,
{ {
self.scopes.push(Scope::Let(bindings)); let base = *self.thunk_count;
let mut guard = ScopeGuard { ctx: self }; *self.thunk_count += keys.len();
f(guard.as_ctx()) let iter = keys
.iter()
.enumerate()
.map(|(offset, &key)| (key, ThunkId(base + offset)));
self.scopes.push(Scope::Let(iter.collect()));
let (vals, ret) = {
let mut guard = ScopeGuard { ctx: self };
f(guard.as_ctx())?
};
assert_eq!(keys.len(), vals.len());
let scope = self.thunk_scopes.last_mut().expect("no active thunk scope");
scope.extend((base..base + keys.len()).map(ThunkId).zip(vals));
Ok(ret)
} }
fn with_param_scope<F, R>(&mut self, param: SymId, arg: ExprId, f: F) -> R fn with_param_scope<F, R>(&mut self, param: SymId, arg: IrRef<'ir>, f: F) -> R
where where
F: FnOnce(&mut Self) -> R, F: FnOnce(&mut Self) -> R,
{ {
@@ -619,11 +628,15 @@ impl DowngradeContext for DowngradeCtx<'_> {
ret ret
} }
fn with_thunk_scope<F, R>(&mut self, f: F) -> (R, Vec<(ExprId, ExprId)>) fn with_thunk_scope<F, R>(
&mut self,
f: F,
) -> (R, bumpalo::collections::Vec<'ir, (ThunkId, IrRef<'ir>)>)
where where
F: FnOnce(&mut Self) -> R, F: FnOnce(&mut Self) -> R,
{ {
self.thunk_scopes.push(Vec::new()); self.thunk_scopes
.push(bumpalo::collections::Vec::new_in(self.bump));
let ret = f(self); let ret = f(self);
( (
ret, ret,
@@ -631,10 +644,17 @@ impl DowngradeContext for DowngradeCtx<'_> {
) )
} }
fn register_thunk(&mut self, slot: ExprId, inner: ExprId) { fn bump(&self) -> &'ir bumpalo::Bump {
self.thunk_scopes self.bump
.last_mut() }
.expect("register_thunk without active scope") }
.push((slot, inner));
impl<'ir, 'ctx: 'ir> DowngradeCtx<'ctx, 'ir> {
fn downgrade_toplevel(mut self, root: rnix::ast::Expr) -> Result<IrRef<'ir>> {
use crate::ir::TopLevel;
let body = root.downgrade(&mut self)?;
let span = body.span();
let thunks = self.thunk_scopes.pop().expect("no thunk scope left???");
Ok(self.new_expr(TopLevel { body, thunks, span }.to_ir()))
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,46 +1,48 @@
use derive_more::{IsVariant, TryUnwrap, Unwrap}; use bumpalo::{Bump, boxed::Box, collections::Vec};
use hashbrown::HashMap;
use rnix::{TextRange, ast}; use rnix::{TextRange, ast};
use string_interner::symbol::SymbolU32; use string_interner::symbol::SymbolU32;
use nix_js_macros::ir; use nix_js_macros::ir;
pub type HashMap<'ir, K, V> = hashbrown::HashMap<K, V, hashbrown::DefaultHashBuilder, &'ir Bump>;
pub type IrRef<'ir> = &'ir Ir<'ir>;
ir! { ir! {
Ir, Ir<'ir>;
Int(i64), Int(i64),
Float(f64), Float(f64),
Bool(bool), Bool(bool),
Null, Null,
Str { pub val: String }, Str { inner: Box<'ir, String> },
AttrSet { pub stcs: HashMap<SymId, (ExprId, rnix::TextRange)>, pub dyns: Vec<(ExprId, ExprId, rnix::TextRange)> }, AttrSet { stcs: HashMap<'ir, SymId, (IrRef<'ir>, TextRange)>, dyns: Vec<'ir, (IrRef<'ir>, IrRef<'ir>, TextRange)> },
List { pub items: Vec<ExprId> }, List { items: Vec<'ir, IrRef<'ir>> },
HasAttr { pub lhs: ExprId, pub rhs: Vec<Attr> }, HasAttr { lhs: IrRef<'ir>, rhs: Vec<'ir, Attr<'ir>> },
BinOp { pub lhs: ExprId, pub rhs: ExprId, pub kind: BinOpKind }, BinOp { lhs: IrRef<'ir>, rhs: IrRef<'ir>, kind: BinOpKind },
UnOp { pub rhs: ExprId, pub kind: UnOpKind }, UnOp { rhs: IrRef<'ir>, kind: UnOpKind },
Select { pub expr: ExprId, pub attrpath: Vec<Attr>, pub default: Option<ExprId> }, Select { expr: IrRef<'ir>, attrpath: Vec<'ir, Attr<'ir>>, default: Option<IrRef<'ir>> },
If { pub cond: ExprId, pub consq: ExprId, pub alter: ExprId }, If { cond: IrRef<'ir>, consq: IrRef<'ir>, alter: IrRef<'ir> },
Call { pub func: ExprId, pub arg: ExprId }, Call { func: IrRef<'ir>, arg: IrRef<'ir> },
Assert { pub assertion: ExprId, pub expr: ExprId, pub assertion_raw: String }, Assert { assertion: IrRef<'ir>, expr: IrRef<'ir>, assertion_raw: String },
ConcatStrings { pub parts: Vec<ExprId>, pub force_string: bool }, ConcatStrings { parts: Vec<'ir, IrRef<'ir>>, force_string: bool },
Path { pub expr: ExprId }, Path { expr: IrRef<'ir> },
Func { pub body: ExprId, pub param: Option<Param>, pub arg: ExprId, pub thunks: Vec<(ExprId, ExprId)> }, Func { body: IrRef<'ir>, param: Option<Param<'ir>>, arg: IrRef<'ir>, thunks: Vec<'ir, (ThunkId, IrRef<'ir>)> },
TopLevel { pub body: ExprId, pub thunks: Vec<(ExprId, ExprId)> }, TopLevel { body: IrRef<'ir>, thunks: Vec<'ir, (ThunkId, IrRef<'ir>)> },
Arg(ArgId), Arg(ArgId),
Thunk(ExprId), Thunk(ThunkId),
Builtins, Builtins,
Builtin(SymId), Builtin(SymId),
CurPos, CurPos,
ReplBinding(SymId), ReplBinding(SymId),
ScopedImportBinding(SymId), ScopedImportBinding(SymId),
WithExpr { pub namespace: ExprId, pub body: ExprId, pub thunks: Vec<(ExprId, ExprId)> }, WithExpr { namespace: IrRef<'ir>, body: IrRef<'ir>, thunks: Vec<'ir, (ThunkId, IrRef<'ir>)> },
WithLookup(SymId), WithLookup(SymId),
} }
#[repr(transparent)] #[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ExprId(pub usize); pub struct ThunkId(pub usize);
pub type SymId = SymbolU32; pub type SymId = SymbolU32;
@@ -50,11 +52,11 @@ pub struct ArgId(pub usize);
/// Represents a key in an attribute path. /// Represents a key in an attribute path.
#[allow(unused)] #[allow(unused)]
#[derive(Debug, TryUnwrap)] #[derive(Debug)]
pub enum Attr { pub enum Attr<'ir> {
/// A dynamic attribute key, which is an expression that must evaluate to a string. /// A dynamic attribute key, which is an expression that must evaluate to a string.
/// Example: `attrs.${key}` /// Example: `attrs.${key}`
Dynamic(ExprId, TextRange), Dynamic(IrRef<'ir>, TextRange),
/// A static attribute key. /// A static attribute key.
/// Example: `attrs.key` /// Example: `attrs.key`
Str(SymId, TextRange), Str(SymId, TextRange),
@@ -135,8 +137,8 @@ impl From<ast::UnaryOpKind> for UnOpKind {
/// Describes the parameters of a function. /// Describes the parameters of a function.
#[derive(Debug)] #[derive(Debug)]
pub struct Param { pub struct Param<'ir> {
pub required: Vec<(SymId, TextRange)>, pub required: Vec<'ir, (SymId, TextRange)>,
pub optional: Vec<(SymId, TextRange)>, pub optional: Vec<'ir, (SymId, TextRange)>,
pub ellipsis: bool, pub ellipsis: bool,
} }

View File

@@ -31,7 +31,7 @@ mod tests {
use std::fs; use std::fs;
use tempfile::TempDir; use tempfile::TempDir;
#[test] #[test_log::test]
fn test_simple_file() { fn test_simple_file() {
let temp = TempDir::new().unwrap(); let temp = TempDir::new().unwrap();
let file_path = temp.path().join("test.txt"); let file_path = temp.path().join("test.txt");
@@ -46,7 +46,7 @@ mod tests {
assert_eq!(hash.len(), 64); assert_eq!(hash.len(), 64);
} }
#[test] #[test_log::test]
fn test_directory() { fn test_directory() {
let temp = TempDir::new().unwrap(); let temp = TempDir::new().unwrap();
fs::write(temp.path().join("a.txt"), "aaa").unwrap(); fs::write(temp.path().join("a.txt"), "aaa").unwrap();

View File

@@ -81,7 +81,7 @@ pub fn validate_store_path(store_dir: &str, path: &str) -> Result<()> {
mod tests { mod tests {
use super::*; use super::*;
#[test] #[test_log::test]
fn test_valid_store_paths() { fn test_valid_store_paths() {
let store_dir = "/nix/store"; let store_dir = "/nix/store";
let valid_paths = vec![ let valid_paths = vec![
@@ -100,7 +100,7 @@ mod tests {
} }
} }
#[test] #[test_log::test]
fn test_invalid_store_paths() { fn test_invalid_store_paths() {
let store_dir = "/nix/store"; let store_dir = "/nix/store";
let invalid_paths = vec![ let invalid_paths = vec![

View File

@@ -1,32 +1,32 @@
use crate::utils::{eval, eval_result}; use crate::utils::{eval, eval_result};
use nix_js::value::Value; use nix_js::value::Value;
#[test] #[test_log::test]
fn arithmetic() { fn arithmetic() {
assert_eq!(eval("1 + 1"), Value::Int(2)); assert_eq!(eval("1 + 1"), Value::Int(2));
} }
#[test] #[test_log::test]
fn simple_function_application() { fn simple_function_application() {
assert_eq!(eval("(x: x) 1"), Value::Int(1)); assert_eq!(eval("(x: x) 1"), Value::Int(1));
} }
#[test] #[test_log::test]
fn curried_function() { fn curried_function() {
assert_eq!(eval("(x: y: x - y) 2 1"), Value::Int(1)); assert_eq!(eval("(x: y: x - y) 2 1"), Value::Int(1));
} }
#[test] #[test_log::test]
fn rec_attrset() { fn rec_attrset() {
assert_eq!(eval("rec { b = a; a = 1; }.b"), Value::Int(1)); assert_eq!(eval("rec { b = a; a = 1; }.b"), Value::Int(1));
} }
#[test] #[test_log::test]
fn let_binding() { fn let_binding() {
assert_eq!(eval("let b = a; a = 1; in b"), Value::Int(1)); assert_eq!(eval("let b = a; a = 1; in b"), Value::Int(1));
} }
#[test] #[test_log::test]
fn fibonacci() { fn fibonacci() {
assert_eq!( assert_eq!(
eval( eval(
@@ -36,7 +36,7 @@ fn fibonacci() {
); );
} }
#[test] #[test_log::test]
fn fixed_point_combinator() { fn fixed_point_combinator() {
assert_eq!( assert_eq!(
eval("((f: let x = f x; in x)(self: { x = 1; y = self.x + 1; })).y"), eval("((f: let x = f x; in x)(self: { x = 1; y = self.x + 1; })).y"),
@@ -44,17 +44,17 @@ fn fixed_point_combinator() {
); );
} }
#[test] #[test_log::test]
fn conditional_true() { fn conditional_true() {
assert_eq!(eval("if true then 1 else 0"), Value::Int(1)); assert_eq!(eval("if true then 1 else 0"), Value::Int(1));
} }
#[test] #[test_log::test]
fn conditional_false() { fn conditional_false() {
assert_eq!(eval("if false then 1 else 0"), Value::Int(0)); assert_eq!(eval("if false then 1 else 0"), Value::Int(0));
} }
#[test] #[test_log::test]
fn nested_let() { fn nested_let() {
assert_eq!( assert_eq!(
eval("let x = 1; in let y = x + 1; z = y + 1; in z"), eval("let x = 1; in let y = x + 1; z = y + 1; in z"),
@@ -62,7 +62,7 @@ fn nested_let() {
); );
} }
#[test] #[test_log::test]
fn rec_inherit_fails() { fn rec_inherit_fails() {
assert!(eval_result("{ inherit x; }").is_err()); assert!(eval_result("{ inherit x; }").is_err());
} }

View File

@@ -2,29 +2,29 @@ use crate::utils::eval;
use nix_js::value::{AttrSet, List, Value}; use nix_js::value::{AttrSet, List, Value};
use std::collections::BTreeMap; use std::collections::BTreeMap;
#[test] #[test_log::test]
fn builtins_accessible() { fn builtins_accessible() {
let result = eval("builtins"); let result = eval("builtins");
assert!(matches!(result, Value::AttrSet(_))); assert!(matches!(result, Value::AttrSet(_)));
} }
#[test] #[test_log::test]
fn builtins_self_reference() { fn builtins_self_reference() {
let result = eval("builtins.builtins"); let result = eval("builtins.builtins");
assert!(matches!(result, Value::AttrSet(_))); assert!(matches!(result, Value::AttrSet(_)));
} }
#[test] #[test_log::test]
fn builtins_add() { fn builtins_add() {
assert_eq!(eval("builtins.add 1 2"), Value::Int(3)); assert_eq!(eval("builtins.add 1 2"), Value::Int(3));
} }
#[test] #[test_log::test]
fn builtins_length() { fn builtins_length() {
assert_eq!(eval("builtins.length [1 2 3]"), Value::Int(3)); assert_eq!(eval("builtins.length [1 2 3]"), Value::Int(3));
} }
#[test] #[test_log::test]
fn builtins_map() { fn builtins_map() {
assert_eq!( assert_eq!(
eval("builtins.map (x: x * 2) [1 2 3]"), eval("builtins.map (x: x * 2) [1 2 3]"),
@@ -32,7 +32,7 @@ fn builtins_map() {
); );
} }
#[test] #[test_log::test]
fn builtins_filter() { fn builtins_filter() {
assert_eq!( assert_eq!(
eval("builtins.filter (x: x > 1) [1 2 3]"), eval("builtins.filter (x: x > 1) [1 2 3]"),
@@ -40,7 +40,7 @@ fn builtins_filter() {
); );
} }
#[test] #[test_log::test]
fn builtins_attrnames() { fn builtins_attrnames() {
let result = eval("builtins.attrNames { a = 1; b = 2; }"); let result = eval("builtins.attrNames { a = 1; b = 2; }");
assert!(matches!(result, Value::List(_))); assert!(matches!(result, Value::List(_)));
@@ -49,12 +49,12 @@ fn builtins_attrnames() {
} }
} }
#[test] #[test_log::test]
fn builtins_head() { fn builtins_head() {
assert_eq!(eval("builtins.head [1 2 3]"), Value::Int(1)); assert_eq!(eval("builtins.head [1 2 3]"), Value::Int(1));
} }
#[test] #[test_log::test]
fn builtins_tail() { fn builtins_tail() {
assert_eq!( assert_eq!(
eval("builtins.tail [1 2 3]"), eval("builtins.tail [1 2 3]"),
@@ -62,17 +62,17 @@ fn builtins_tail() {
); );
} }
#[test] #[test_log::test]
fn builtins_in_let() { fn builtins_in_let() {
assert_eq!(eval("let b = builtins; in b.add 5 3"), Value::Int(8)); assert_eq!(eval("let b = builtins; in b.add 5 3"), Value::Int(8));
} }
#[test] #[test_log::test]
fn builtins_in_with() { fn builtins_in_with() {
assert_eq!(eval("with builtins; add 10 20"), Value::Int(30)); assert_eq!(eval("with builtins; add 10 20"), Value::Int(30));
} }
#[test] #[test_log::test]
fn builtins_nested_calls() { fn builtins_nested_calls() {
assert_eq!( assert_eq!(
eval("builtins.add (builtins.mul 2 3) (builtins.sub 10 5)"), eval("builtins.add (builtins.mul 2 3) (builtins.sub 10 5)"),
@@ -80,32 +80,32 @@ fn builtins_nested_calls() {
); );
} }
#[test] #[test_log::test]
fn builtins_is_list() { fn builtins_is_list() {
assert_eq!(eval("builtins.isList [1 2 3]"), Value::Bool(true)); assert_eq!(eval("builtins.isList [1 2 3]"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn builtins_is_attrs() { fn builtins_is_attrs() {
assert_eq!(eval("builtins.isAttrs { a = 1; }"), Value::Bool(true)); assert_eq!(eval("builtins.isAttrs { a = 1; }"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn builtins_is_function() { fn builtins_is_function() {
assert_eq!(eval("builtins.isFunction (x: x)"), Value::Bool(true)); assert_eq!(eval("builtins.isFunction (x: x)"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn builtins_is_null() { fn builtins_is_null() {
assert_eq!(eval("builtins.isNull null"), Value::Bool(true)); assert_eq!(eval("builtins.isNull null"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn builtins_is_bool() { fn builtins_is_bool() {
assert_eq!(eval("builtins.isBool true"), Value::Bool(true)); assert_eq!(eval("builtins.isBool true"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn builtins_shadowing() { fn builtins_shadowing() {
assert_eq!( assert_eq!(
eval("let builtins = { add = x: y: x - y; }; in builtins.add 5 3"), eval("let builtins = { add = x: y: x - y; }; in builtins.add 5 3"),
@@ -113,13 +113,13 @@ fn builtins_shadowing() {
); );
} }
#[test] #[test_log::test]
fn builtins_lazy_evaluation() { fn builtins_lazy_evaluation() {
let result = eval("builtins.builtins.builtins.add 1 1"); let result = eval("builtins.builtins.builtins.add 1 1");
assert_eq!(result, Value::Int(2)); assert_eq!(result, Value::Int(2));
} }
#[test] #[test_log::test]
fn builtins_foldl() { fn builtins_foldl() {
assert_eq!( assert_eq!(
eval("builtins.foldl' (acc: x: acc + x) 0 [1 2 3 4 5]"), eval("builtins.foldl' (acc: x: acc + x) 0 [1 2 3 4 5]"),
@@ -127,13 +127,13 @@ fn builtins_foldl() {
); );
} }
#[test] #[test_log::test]
fn builtins_elem() { fn builtins_elem() {
assert_eq!(eval("builtins.elem 2 [1 2 3]"), Value::Bool(true)); assert_eq!(eval("builtins.elem 2 [1 2 3]"), Value::Bool(true));
assert_eq!(eval("builtins.elem 5 [1 2 3]"), Value::Bool(false)); assert_eq!(eval("builtins.elem 5 [1 2 3]"), Value::Bool(false));
} }
#[test] #[test_log::test]
fn builtins_concat_lists() { fn builtins_concat_lists() {
assert_eq!( assert_eq!(
eval("builtins.concatLists [[1 2] [3 4] [5]]"), eval("builtins.concatLists [[1 2] [3 4] [5]]"),
@@ -147,7 +147,7 @@ fn builtins_concat_lists() {
); );
} }
#[test] #[test_log::test]
fn builtins_compare_versions_basic() { fn builtins_compare_versions_basic() {
assert_eq!( assert_eq!(
eval("builtins.compareVersions \"1.0\" \"2.3\""), eval("builtins.compareVersions \"1.0\" \"2.3\""),
@@ -171,7 +171,7 @@ fn builtins_compare_versions_basic() {
); );
} }
#[test] #[test_log::test]
fn builtins_compare_versions_components() { fn builtins_compare_versions_components() {
assert_eq!( assert_eq!(
eval("builtins.compareVersions \"2.3.1\" \"2.3\""), eval("builtins.compareVersions \"2.3.1\" \"2.3\""),
@@ -183,7 +183,7 @@ fn builtins_compare_versions_components() {
); );
} }
#[test] #[test_log::test]
fn builtins_compare_versions_numeric_vs_alpha() { fn builtins_compare_versions_numeric_vs_alpha() {
// Numeric component comes before alpha component // Numeric component comes before alpha component
assert_eq!( assert_eq!(
@@ -196,7 +196,7 @@ fn builtins_compare_versions_numeric_vs_alpha() {
); );
} }
#[test] #[test_log::test]
fn builtins_compare_versions_pre() { fn builtins_compare_versions_pre() {
// "pre" is special: comes before everything except another "pre" // "pre" is special: comes before everything except another "pre"
assert_eq!( assert_eq!(
@@ -217,7 +217,7 @@ fn builtins_compare_versions_pre() {
); );
} }
#[test] #[test_log::test]
fn builtins_compare_versions_alpha() { fn builtins_compare_versions_alpha() {
// Alphabetic comparison // Alphabetic comparison
assert_eq!( assert_eq!(
@@ -230,7 +230,7 @@ fn builtins_compare_versions_alpha() {
); );
} }
#[test] #[test_log::test]
fn builtins_compare_versions_symmetry() { fn builtins_compare_versions_symmetry() {
// Test symmetry: compareVersions(a, b) == -compareVersions(b, a) // Test symmetry: compareVersions(a, b) == -compareVersions(b, a)
assert_eq!( assert_eq!(
@@ -243,7 +243,7 @@ fn builtins_compare_versions_symmetry() {
); );
} }
#[test] #[test_log::test]
fn builtins_compare_versions_complex() { fn builtins_compare_versions_complex() {
// Complex version strings with multiple components // Complex version strings with multiple components
assert_eq!( assert_eq!(
@@ -260,7 +260,7 @@ fn builtins_compare_versions_complex() {
); );
} }
#[test] #[test_log::test]
fn builtins_generic_closure() { fn builtins_generic_closure() {
assert_eq!( assert_eq!(
eval( eval(
@@ -276,7 +276,7 @@ fn builtins_generic_closure() {
); );
} }
#[test] #[test_log::test]
fn builtins_function_args() { fn builtins_function_args() {
assert_eq!( assert_eq!(
eval("builtins.functionArgs (x: 1)"), eval("builtins.functionArgs (x: 1)"),
@@ -313,7 +313,7 @@ fn builtins_function_args() {
); );
} }
#[test] #[test_log::test]
fn builtins_parse_drv_name() { fn builtins_parse_drv_name() {
let result = eval(r#"builtins.parseDrvName "nix-js-0.1.0pre""#).unwrap_attr_set(); let result = eval(r#"builtins.parseDrvName "nix-js-0.1.0pre""#).unwrap_attr_set();
assert_eq!(result.get("name"), Some(&Value::String("nix-js".into()))); assert_eq!(result.get("name"), Some(&Value::String("nix-js".into())));

View File

@@ -1,7 +1,7 @@
use crate::utils::eval_result; use crate::utils::eval_result;
use nix_js::value::Value; use nix_js::value::Value;
#[test] #[test_log::test]
fn to_file_simple() { fn to_file_simple() {
let result = let result =
eval_result(r#"builtins.toFile "hello.txt" "Hello, World!""#).expect("Failed to evaluate"); eval_result(r#"builtins.toFile "hello.txt" "Hello, World!""#).expect("Failed to evaluate");
@@ -18,7 +18,7 @@ fn to_file_simple() {
} }
} }
#[test] #[test_log::test]
fn to_file_with_references() { fn to_file_with_references() {
let result = eval_result( let result = eval_result(
r#" r#"
@@ -41,7 +41,7 @@ fn to_file_with_references() {
} }
} }
#[test] #[test_log::test]
fn to_file_invalid_name_with_slash() { fn to_file_invalid_name_with_slash() {
let result = eval_result(r#"builtins.toFile "foo/bar.txt" "content""#); let result = eval_result(r#"builtins.toFile "foo/bar.txt" "content""#);
@@ -54,7 +54,7 @@ fn to_file_invalid_name_with_slash() {
); );
} }
#[test] #[test_log::test]
fn to_file_invalid_name_dot() { fn to_file_invalid_name_dot() {
let result = eval_result(r#"builtins.toFile "." "content""#); let result = eval_result(r#"builtins.toFile "." "content""#);
@@ -62,7 +62,7 @@ fn to_file_invalid_name_dot() {
assert!(result.unwrap_err().to_string().contains("invalid name")); assert!(result.unwrap_err().to_string().contains("invalid name"));
} }
#[test] #[test_log::test]
fn to_file_invalid_name_dotdot() { fn to_file_invalid_name_dotdot() {
let result = eval_result(r#"builtins.toFile ".." "content""#); let result = eval_result(r#"builtins.toFile ".." "content""#);
@@ -70,7 +70,7 @@ fn to_file_invalid_name_dotdot() {
assert!(result.unwrap_err().to_string().contains("invalid name")); assert!(result.unwrap_err().to_string().contains("invalid name"));
} }
#[test] #[test_log::test]
fn store_path_validation_not_in_store() { fn store_path_validation_not_in_store() {
let result = eval_result(r#"builtins.storePath "/tmp/foo""#); let result = eval_result(r#"builtins.storePath "/tmp/foo""#);
@@ -83,7 +83,7 @@ fn store_path_validation_not_in_store() {
); );
} }
#[test] #[test_log::test]
fn store_path_validation_malformed_hash() { fn store_path_validation_malformed_hash() {
let dummy_file_result = eval_result(r#"builtins.toFile "dummy.txt" "content""#) let dummy_file_result = eval_result(r#"builtins.toFile "dummy.txt" "content""#)
.expect("Failed to create dummy file"); .expect("Failed to create dummy file");
@@ -111,7 +111,7 @@ fn store_path_validation_malformed_hash() {
); );
} }
#[test] #[test_log::test]
fn store_path_validation_missing_name() { fn store_path_validation_missing_name() {
let dummy_file_result = eval_result(r#"builtins.toFile "dummy.txt" "content""#) let dummy_file_result = eval_result(r#"builtins.toFile "dummy.txt" "content""#)
.expect("Failed to create dummy file"); .expect("Failed to create dummy file");
@@ -139,7 +139,7 @@ fn store_path_validation_missing_name() {
); );
} }
#[test] #[test_log::test]
fn to_file_curried_application() { fn to_file_curried_application() {
let result = eval_result( let result = eval_result(
r#" r#"
@@ -161,7 +161,7 @@ fn to_file_curried_application() {
} }
} }
#[test] #[test_log::test]
fn to_file_number_conversion() { fn to_file_number_conversion() {
let result = eval_result(r#"builtins.toFile "number.txt" (builtins.toString 42)"#) let result = eval_result(r#"builtins.toFile "number.txt" (builtins.toString 42)"#)
.expect("Failed to evaluate"); .expect("Failed to evaluate");
@@ -175,7 +175,7 @@ fn to_file_number_conversion() {
} }
} }
#[test] #[test_log::test]
fn to_file_list_conversion() { fn to_file_list_conversion() {
let result = eval_result( let result = eval_result(
r#"builtins.toFile "list.txt" (builtins.concatStringsSep "\n" ["line1" "line2" "line3"])"#, r#"builtins.toFile "list.txt" (builtins.concatStringsSep "\n" ["line1" "line2" "line3"])"#,

View File

@@ -1,7 +1,7 @@
use crate::utils::{eval_deep, eval_deep_result}; use crate::utils::{eval_deep, eval_deep_result};
use nix_js::value::Value; use nix_js::value::Value;
#[test] #[test_log::test]
fn add_operator_preserves_derivation_context() { fn add_operator_preserves_derivation_context() {
let result = eval_deep( let result = eval_deep(
r#" r#"
@@ -37,7 +37,7 @@ fn add_operator_preserves_derivation_context() {
assert_eq!(result, nix_result); assert_eq!(result, nix_result);
} }
#[test] #[test_log::test]
fn derivation_minimal() { fn derivation_minimal() {
let result = eval_deep( let result = eval_deep(
r#"derivation { name = "hello"; builder = "/bin/sh"; system = "x86_64-linux"; }"#, r#"derivation { name = "hello"; builder = "/bin/sh"; system = "x86_64-linux"; }"#,
@@ -75,7 +75,7 @@ fn derivation_minimal() {
} }
} }
#[test] #[test_log::test]
fn derivation_with_args() { fn derivation_with_args() {
let result = eval_deep( let result = eval_deep(
r#"derivation { r#"derivation {
@@ -97,7 +97,7 @@ fn derivation_with_args() {
} }
} }
#[test] #[test_log::test]
fn derivation_to_string() { fn derivation_to_string() {
let result = eval_deep( 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"; })"#,
@@ -109,7 +109,7 @@ fn derivation_to_string() {
} }
} }
#[test] #[test_log::test]
fn derivation_missing_name() { fn derivation_missing_name() {
let result = let result =
eval_deep_result(r#"derivation { builder = "/bin/sh"; system = "x86_64-linux"; }"#); eval_deep_result(r#"derivation { builder = "/bin/sh"; system = "x86_64-linux"; }"#);
@@ -119,7 +119,7 @@ fn derivation_missing_name() {
assert!(err_msg.contains("missing required attribute 'name'")); assert!(err_msg.contains("missing required attribute 'name'"));
} }
#[test] #[test_log::test]
fn derivation_invalid_name_with_drv_suffix() { fn derivation_invalid_name_with_drv_suffix() {
let result = eval_deep_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"; }"#,
@@ -130,7 +130,7 @@ fn derivation_invalid_name_with_drv_suffix() {
assert!(err_msg.contains("cannot end with .drv")); assert!(err_msg.contains("cannot end with .drv"));
} }
#[test] #[test_log::test]
fn derivation_missing_builder() { fn derivation_missing_builder() {
let result = eval_deep_result(r#"derivation { name = "test"; system = "x86_64-linux"; }"#); let result = eval_deep_result(r#"derivation { name = "test"; system = "x86_64-linux"; }"#);
@@ -139,7 +139,7 @@ fn derivation_missing_builder() {
assert!(err_msg.contains("missing required attribute 'builder'")); assert!(err_msg.contains("missing required attribute 'builder'"));
} }
#[test] #[test_log::test]
fn derivation_missing_system() { fn derivation_missing_system() {
let result = eval_deep_result(r#"derivation { name = "test"; builder = "/bin/sh"; }"#); let result = eval_deep_result(r#"derivation { name = "test"; builder = "/bin/sh"; }"#);
@@ -148,7 +148,7 @@ fn derivation_missing_system() {
assert!(err_msg.contains("missing required attribute 'system'")); assert!(err_msg.contains("missing required attribute 'system'"));
} }
#[test] #[test_log::test]
fn derivation_with_env_vars() { fn derivation_with_env_vars() {
let result = eval_deep( let result = eval_deep(
r#"derivation { r#"derivation {
@@ -169,7 +169,7 @@ fn derivation_with_env_vars() {
} }
} }
#[test] #[test_log::test]
fn derivation_strict() { fn derivation_strict() {
let result = eval_deep( 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"; }"#,
@@ -186,7 +186,7 @@ fn derivation_strict() {
} }
} }
#[test] #[test_log::test]
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"; }"#;
@@ -202,7 +202,7 @@ fn derivation_deterministic_paths() {
} }
} }
#[test] #[test_log::test]
fn derivation_escaping_in_aterm() { fn derivation_escaping_in_aterm() {
let result = eval_deep( let result = eval_deep(
r#"derivation { r#"derivation {
@@ -222,7 +222,7 @@ fn derivation_escaping_in_aterm() {
} }
} }
#[test] #[test_log::test]
fn multi_output_two_outputs() { fn multi_output_two_outputs() {
let drv = eval_deep( let drv = eval_deep(
r#"derivation { r#"derivation {
@@ -265,7 +265,7 @@ fn multi_output_two_outputs() {
} }
} }
#[test] #[test_log::test]
fn multi_output_three_outputs() { fn multi_output_three_outputs() {
let result = eval_deep( let result = eval_deep(
r#"derivation { r#"derivation {
@@ -313,7 +313,7 @@ fn multi_output_three_outputs() {
} }
} }
#[test] #[test_log::test]
fn multi_output_backward_compat() { fn multi_output_backward_compat() {
let result = eval_deep( let result = eval_deep(
r#"derivation { r#"derivation {
@@ -339,7 +339,7 @@ fn multi_output_backward_compat() {
} }
} }
#[test] #[test_log::test]
fn multi_output_deterministic() { fn multi_output_deterministic() {
let result1 = eval_deep( let result1 = eval_deep(
r#"derivation { r#"derivation {
@@ -362,7 +362,7 @@ fn multi_output_deterministic() {
assert_eq!(result1, result2); assert_eq!(result1, result2);
} }
#[test] #[test_log::test]
fn fixed_output_sha256_flat() { fn fixed_output_sha256_flat() {
let result = eval_deep( let result = eval_deep(
r#"derivation { r#"derivation {
@@ -399,7 +399,7 @@ fn fixed_output_sha256_flat() {
} }
} }
#[test] #[test_log::test]
fn fixed_output_missing_hashalgo() { fn fixed_output_missing_hashalgo() {
assert!( assert!(
eval_deep_result( eval_deep_result(
@@ -414,7 +414,7 @@ fn fixed_output_missing_hashalgo() {
); );
} }
#[test] #[test_log::test]
fn fixed_output_recursive_mode() { fn fixed_output_recursive_mode() {
let result = eval_deep( let result = eval_deep(
r#"derivation { r#"derivation {
@@ -444,7 +444,7 @@ fn fixed_output_recursive_mode() {
} }
} }
#[test] #[test_log::test]
fn fixed_output_rejects_multi_output() { fn fixed_output_rejects_multi_output() {
let result = eval_deep_result( let result = eval_deep_result(
r#"derivation { r#"derivation {
@@ -462,7 +462,7 @@ fn fixed_output_rejects_multi_output() {
assert!(err_msg.contains("fixed-output") && err_msg.contains("one")); assert!(err_msg.contains("fixed-output") && err_msg.contains("one"));
} }
#[test] #[test_log::test]
fn fixed_output_invalid_hash_mode() { fn fixed_output_invalid_hash_mode() {
let result = eval_deep_result( let result = eval_deep_result(
r#"derivation { r#"derivation {
@@ -479,7 +479,7 @@ fn fixed_output_invalid_hash_mode() {
assert!(err_msg.contains("outputHashMode") && err_msg.contains("invalid")); assert!(err_msg.contains("outputHashMode") && err_msg.contains("invalid"));
} }
#[test] #[test_log::test]
fn structured_attrs_basic() { fn structured_attrs_basic() {
let result = eval_deep( let result = eval_deep(
r#"derivation { r#"derivation {
@@ -504,7 +504,7 @@ fn structured_attrs_basic() {
} }
} }
#[test] #[test_log::test]
fn structured_attrs_nested() { fn structured_attrs_nested() {
let result = eval_deep( let result = eval_deep(
r#"derivation { r#"derivation {
@@ -525,7 +525,7 @@ fn structured_attrs_nested() {
} }
} }
#[test] #[test_log::test]
fn structured_attrs_rejects_functions() { fn structured_attrs_rejects_functions() {
let result = eval_deep_result( let result = eval_deep_result(
r#"derivation { r#"derivation {
@@ -542,7 +542,7 @@ fn structured_attrs_rejects_functions() {
assert!(err_msg.contains("cannot convert lambda to JSON")); assert!(err_msg.contains("cannot convert lambda to JSON"));
} }
#[test] #[test_log::test]
fn structured_attrs_false() { fn structured_attrs_false() {
let result = eval_deep( let result = eval_deep(
r#"derivation { r#"derivation {
@@ -565,7 +565,7 @@ fn structured_attrs_false() {
} }
} }
#[test] #[test_log::test]
fn ignore_nulls_true() { fn ignore_nulls_true() {
let result = eval_deep( let result = eval_deep(
r#"derivation { r#"derivation {
@@ -587,7 +587,7 @@ fn ignore_nulls_true() {
} }
} }
#[test] #[test_log::test]
fn ignore_nulls_false() { fn ignore_nulls_false() {
let result = eval_deep( let result = eval_deep(
r#"derivation { r#"derivation {
@@ -610,7 +610,7 @@ fn ignore_nulls_false() {
} }
} }
#[test] #[test_log::test]
fn ignore_nulls_with_structured_attrs() { fn ignore_nulls_with_structured_attrs() {
let result = eval_deep( let result = eval_deep(
r#"derivation { r#"derivation {
@@ -634,7 +634,7 @@ fn ignore_nulls_with_structured_attrs() {
} }
} }
#[test] #[test_log::test]
fn all_features_combined() { fn all_features_combined() {
let result = eval_deep( let result = eval_deep(
r#"derivation { r#"derivation {
@@ -661,7 +661,7 @@ fn all_features_combined() {
} }
} }
#[test] #[test_log::test]
fn fixed_output_with_structured_attrs() { fn fixed_output_with_structured_attrs() {
let result = eval_deep( let result = eval_deep(
r#"derivation { r#"derivation {

View File

@@ -1,6 +1,6 @@
use crate::utils::eval; use crate::utils::eval;
#[test] #[test_log::test]
fn test_find_file_corepkg_fetchurl() { fn test_find_file_corepkg_fetchurl() {
let result = eval( let result = eval(
r#" r#"
@@ -15,13 +15,13 @@ fn test_find_file_corepkg_fetchurl() {
assert!(result.to_string().contains("fetchurl.nix")); assert!(result.to_string().contains("fetchurl.nix"));
} }
#[test] #[test_log::test]
fn test_lookup_path_syntax() { fn test_lookup_path_syntax() {
let result = eval(r#"<nix/fetchurl.nix>"#); let result = eval(r#"<nix/fetchurl.nix>"#);
assert!(result.to_string().contains("fetchurl.nix")); assert!(result.to_string().contains("fetchurl.nix"));
} }
#[test] #[test_log::test]
fn test_import_corepkg() { fn test_import_corepkg() {
let result = eval( let result = eval(
r#" r#"

View File

@@ -1,22 +1,22 @@
use crate::utils::{eval, eval_result}; use crate::utils::{eval, eval_result};
use nix_js::value::{List, Value}; use nix_js::value::{List, Value};
#[test] #[test_log::test]
fn true_literal() { fn true_literal() {
assert_eq!(eval("true"), Value::Bool(true)); assert_eq!(eval("true"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn false_literal() { fn false_literal() {
assert_eq!(eval("false"), Value::Bool(false)); assert_eq!(eval("false"), Value::Bool(false));
} }
#[test] #[test_log::test]
fn null_literal() { fn null_literal() {
assert_eq!(eval("null"), Value::Null); assert_eq!(eval("null"), Value::Null);
} }
#[test] #[test_log::test]
fn map_function() { fn map_function() {
assert_eq!( assert_eq!(
eval("map (x: x * 2) [1 2 3]"), eval("map (x: x * 2) [1 2 3]"),
@@ -24,23 +24,23 @@ fn map_function() {
); );
} }
#[test] #[test_log::test]
fn is_null_function() { fn is_null_function() {
assert_eq!(eval("isNull null"), Value::Bool(true)); assert_eq!(eval("isNull null"), Value::Bool(true));
assert_eq!(eval("isNull 5"), Value::Bool(false)); assert_eq!(eval("isNull 5"), Value::Bool(false));
} }
#[test] #[test_log::test]
fn shadow_true() { fn shadow_true() {
assert_eq!(eval("let true = false; in true"), Value::Bool(false)); assert_eq!(eval("let true = false; in true"), Value::Bool(false));
} }
#[test] #[test_log::test]
fn shadow_map() { fn shadow_map() {
assert_eq!(eval("let map = x: y: x; in map 1 2"), Value::Int(1)); assert_eq!(eval("let map = x: y: x; in map 1 2"), Value::Int(1));
} }
#[test] #[test_log::test]
fn mixed_usage() { fn mixed_usage() {
assert_eq!( assert_eq!(
eval("if true then map (x: x + 1) [1 2] else []"), eval("if true then map (x: x + 1) [1 2] else []"),
@@ -48,7 +48,7 @@ fn mixed_usage() {
); );
} }
#[test] #[test_log::test]
fn in_let_bindings() { fn in_let_bindings() {
assert_eq!( assert_eq!(
eval("let x = true; y = false; in x && y"), eval("let x = true; y = false; in x && y"),
@@ -56,18 +56,18 @@ fn in_let_bindings() {
); );
} }
#[test] #[test_log::test]
fn shadow_in_function() { fn shadow_in_function() {
assert_eq!(eval("(true: true) false"), Value::Bool(false)); assert_eq!(eval("(true: true) false"), Value::Bool(false));
} }
#[test] #[test_log::test]
fn throw_function() { fn throw_function() {
let result = eval_result("throw \"error message\""); let result = eval_result("throw \"error message\"");
assert!(result.is_err()); assert!(result.is_err());
} }
#[test] #[test_log::test]
fn to_string_function() { fn to_string_function() {
assert_eq!(eval("toString 42"), Value::String("42".to_string())); assert_eq!(eval("toString 42"), Value::String("42".to_string()));
} }

View File

@@ -1,18 +1,18 @@
use crate::utils::{eval, eval_result}; use crate::utils::{eval, eval_result};
use nix_js::value::Value; use nix_js::value::Value;
#[test] #[test_log::test]
fn required_parameters() { fn required_parameters() {
assert_eq!(eval("({ a, b }: a + b) { a = 1; b = 2; }"), Value::Int(3)); assert_eq!(eval("({ a, b }: a + b) { a = 1; b = 2; }"), Value::Int(3));
} }
#[test] #[test_log::test]
fn missing_required_parameter() { fn missing_required_parameter() {
let result = eval_result("({ a, b }: a + b) { a = 1; }"); let result = eval_result("({ a, b }: a + b) { a = 1; }");
assert!(result.is_err()); assert!(result.is_err());
} }
#[test] #[test_log::test]
fn all_required_parameters_present() { fn all_required_parameters_present() {
assert_eq!( assert_eq!(
eval("({ x, y, z }: x + y + z) { x = 1; y = 2; z = 3; }"), eval("({ x, y, z }: x + y + z) { x = 1; y = 2; z = 3; }"),
@@ -20,13 +20,13 @@ fn all_required_parameters_present() {
); );
} }
#[test] #[test_log::test]
fn reject_unexpected_arguments() { fn reject_unexpected_arguments() {
let result = eval_result("({ a, b }: a + b) { a = 1; b = 2; c = 3; }"); let result = eval_result("({ a, b }: a + b) { a = 1; b = 2; c = 3; }");
assert!(result.is_err()); assert!(result.is_err());
} }
#[test] #[test_log::test]
fn ellipsis_accepts_extra_arguments() { fn ellipsis_accepts_extra_arguments() {
assert_eq!( assert_eq!(
eval("({ a, b, ... }: a + b) { a = 1; b = 2; c = 3; }"), eval("({ a, b, ... }: a + b) { a = 1; b = 2; c = 3; }"),
@@ -34,12 +34,12 @@ fn ellipsis_accepts_extra_arguments() {
); );
} }
#[test] #[test_log::test]
fn default_parameters() { fn default_parameters() {
assert_eq!(eval("({ a, b ? 5 }: a + b) { a = 1; }"), Value::Int(6)); assert_eq!(eval("({ a, b ? 5 }: a + b) { a = 1; }"), Value::Int(6));
} }
#[test] #[test_log::test]
fn override_default_parameter() { fn override_default_parameter() {
assert_eq!( assert_eq!(
eval("({ a, b ? 5 }: a + b) { a = 1; b = 10; }"), eval("({ a, b ? 5 }: a + b) { a = 1; b = 10; }"),
@@ -47,7 +47,7 @@ fn override_default_parameter() {
); );
} }
#[test] #[test_log::test]
fn at_pattern_alias() { fn at_pattern_alias() {
assert_eq!( assert_eq!(
eval("(args@{ a, b }: args.a + args.b) { a = 1; b = 2; }"), eval("(args@{ a, b }: args.a + args.b) { a = 1; b = 2; }"),
@@ -55,17 +55,17 @@ fn at_pattern_alias() {
); );
} }
#[test] #[test_log::test]
fn simple_parameter_no_validation() { fn simple_parameter_no_validation() {
assert_eq!(eval("(x: x.a + x.b) { a = 1; b = 2; }"), Value::Int(3)); assert_eq!(eval("(x: x.a + x.b) { a = 1; b = 2; }"), Value::Int(3));
} }
#[test] #[test_log::test]
fn simple_parameter_accepts_any_argument() { fn simple_parameter_accepts_any_argument() {
assert_eq!(eval("(x: x) 42"), Value::Int(42)); assert_eq!(eval("(x: x) 42"), Value::Int(42));
} }
#[test] #[test_log::test]
fn nested_function_parameters() { fn nested_function_parameters() {
assert_eq!( assert_eq!(
eval("({ a }: { b }: a + b) { a = 5; } { b = 3; }"), eval("({ a }: { b }: a + b) { a = 5; } { b = 3; }"),
@@ -73,12 +73,12 @@ fn nested_function_parameters() {
); );
} }
#[test] #[test_log::test]
fn pattern_param_simple_reference_in_default() { fn pattern_param_simple_reference_in_default() {
assert_eq!(eval("({ a, b ? a }: b) { a = 10; }"), Value::Int(10)); assert_eq!(eval("({ a, b ? a }: b) { a = 10; }"), Value::Int(10));
} }
#[test] #[test_log::test]
fn pattern_param_multiple_references_in_default() { fn pattern_param_multiple_references_in_default() {
assert_eq!( assert_eq!(
eval("({ a, b ? a + 5, c ? 1 }: b + c) { a = 10; }"), eval("({ a, b ? a + 5, c ? 1 }: b + c) { a = 10; }"),
@@ -86,7 +86,7 @@ fn pattern_param_multiple_references_in_default() {
); );
} }
#[test] #[test_log::test]
fn pattern_param_mutual_reference() { fn pattern_param_mutual_reference() {
assert_eq!( assert_eq!(
eval("({ a, b ? c + 1, c ? 5 }: b) { a = 1; }"), eval("({ a, b ? c + 1, c ? 5 }: b) { a = 1; }"),
@@ -94,7 +94,7 @@ fn pattern_param_mutual_reference() {
); );
} }
#[test] #[test_log::test]
fn pattern_param_override_mutual_reference() { fn pattern_param_override_mutual_reference() {
assert_eq!( assert_eq!(
eval("({ a, b ? c + 1, c ? 5 }: b) { a = 1; c = 10; }"), eval("({ a, b ? c + 1, c ? 5 }: b) { a = 1; c = 10; }"),
@@ -102,7 +102,7 @@ fn pattern_param_override_mutual_reference() {
); );
} }
#[test] #[test_log::test]
fn pattern_param_reference_list() { fn pattern_param_reference_list() {
assert_eq!( assert_eq!(
eval("({ a, b ? [ a 2 ] }: builtins.elemAt b 0) { a = 42; }"), eval("({ a, b ? [ a 2 ] }: builtins.elemAt b 0) { a = 42; }"),
@@ -110,7 +110,7 @@ fn pattern_param_reference_list() {
); );
} }
#[test] #[test_log::test]
fn pattern_param_alias_in_default() { fn pattern_param_alias_in_default() {
assert_eq!( assert_eq!(
eval("(args@{ a, b ? args.a + 10 }: b) { a = 5; }"), eval("(args@{ a, b ? args.a + 10 }: b) { a = 5; }"),

View File

@@ -3,7 +3,7 @@ use nix_js::context::Context;
use nix_js::error::Source; use nix_js::error::Source;
use nix_js::value::Value; use nix_js::value::Value;
#[test] #[test_log::test]
fn import_absolute_path() { fn import_absolute_path() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let lib_path = temp_dir.path().join("nix_test_lib.nix"); let lib_path = temp_dir.path().join("nix_test_lib.nix");
@@ -14,7 +14,7 @@ fn import_absolute_path() {
assert_eq!(eval(&expr), Value::Int(8)); assert_eq!(eval(&expr), Value::Int(8));
} }
#[test] #[test_log::test]
fn import_nested() { fn import_nested() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
@@ -32,7 +32,7 @@ fn import_nested() {
assert_eq!(eval(&expr), Value::Int(30)); assert_eq!(eval(&expr), Value::Int(30));
} }
#[test] #[test_log::test]
fn import_relative_path() { fn import_relative_path() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let subdir = temp_dir.path().join("subdir"); let subdir = temp_dir.path().join("subdir");
@@ -63,7 +63,7 @@ fn import_relative_path() {
assert_eq!(eval(&expr), Value::Int(7)); assert_eq!(eval(&expr), Value::Int(7));
} }
#[test] #[test_log::test]
fn import_returns_function() { fn import_returns_function() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let func_path = temp_dir.path().join("nix_test_func.nix"); let func_path = temp_dir.path().join("nix_test_func.nix");
@@ -73,7 +73,7 @@ fn import_returns_function() {
assert_eq!(eval(&expr), Value::Int(10)); assert_eq!(eval(&expr), Value::Int(10));
} }
#[test] #[test_log::test]
fn import_with_complex_dependency_graph() { fn import_with_complex_dependency_graph() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
@@ -94,7 +94,7 @@ fn import_with_complex_dependency_graph() {
// Tests for builtins.path // Tests for builtins.path
#[test] #[test_log::test]
fn path_with_file() { fn path_with_file() {
let mut ctx = Context::new().unwrap(); let mut ctx = Context::new().unwrap();
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
@@ -113,7 +113,7 @@ fn path_with_file() {
} }
} }
#[test] #[test_log::test]
fn path_with_custom_name() { fn path_with_custom_name() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let test_file = temp_dir.path().join("original.txt"); let test_file = temp_dir.path().join("original.txt");
@@ -133,7 +133,7 @@ fn path_with_custom_name() {
} }
} }
#[test] #[test_log::test]
fn path_with_directory_recursive() { fn path_with_directory_recursive() {
let mut ctx = Context::new().unwrap(); let mut ctx = Context::new().unwrap();
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
@@ -156,7 +156,7 @@ fn path_with_directory_recursive() {
} }
} }
#[test] #[test_log::test]
fn path_flat_with_file() { fn path_flat_with_file() {
let mut ctx = Context::new().unwrap(); let mut ctx = Context::new().unwrap();
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
@@ -176,7 +176,7 @@ fn path_flat_with_file() {
} }
} }
#[test] #[test_log::test]
fn path_flat_with_directory_fails() { fn path_flat_with_directory_fails() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let test_dir = temp_dir.path().join("mydir"); let test_dir = temp_dir.path().join("mydir");
@@ -193,7 +193,7 @@ fn path_flat_with_directory_fails() {
assert!(err_msg.contains("recursive") || err_msg.contains("regular file")); assert!(err_msg.contains("recursive") || err_msg.contains("regular file"));
} }
#[test] #[test_log::test]
fn path_nonexistent_fails() { fn path_nonexistent_fails() {
let expr = r#"builtins.path { path = "/nonexistent/path/that/should/not/exist"; }"#; let expr = r#"builtins.path { path = "/nonexistent/path/that/should/not/exist"; }"#;
let result = eval_result(expr); let result = eval_result(expr);
@@ -203,7 +203,7 @@ fn path_nonexistent_fails() {
assert!(err_msg.contains("does not exist")); assert!(err_msg.contains("does not exist"));
} }
#[test] #[test_log::test]
fn path_missing_path_param() { fn path_missing_path_param() {
let expr = r#"builtins.path { name = "test"; }"#; let expr = r#"builtins.path { name = "test"; }"#;
let result = eval_result(expr); let result = eval_result(expr);
@@ -213,7 +213,7 @@ fn path_missing_path_param() {
assert!(err_msg.contains("path") && err_msg.contains("required")); assert!(err_msg.contains("path") && err_msg.contains("required"));
} }
#[test] #[test_log::test]
fn path_with_sha256() { fn path_with_sha256() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let test_file = temp_dir.path().join("hash_test.txt"); let test_file = temp_dir.path().join("hash_test.txt");
@@ -240,7 +240,7 @@ fn path_with_sha256() {
assert_eq!(store_path1, store_path2); assert_eq!(store_path1, store_path2);
} }
#[test] #[test_log::test]
fn path_deterministic() { fn path_deterministic() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let test_file = temp_dir.path().join("deterministic.txt"); let test_file = temp_dir.path().join("deterministic.txt");
@@ -258,7 +258,7 @@ fn path_deterministic() {
assert_eq!(result1, result2); assert_eq!(result1, result2);
} }
#[test] #[test_log::test]
fn read_file_type_regular_file() { fn read_file_type_regular_file() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let test_file = temp_dir.path().join("test.txt"); let test_file = temp_dir.path().join("test.txt");
@@ -268,7 +268,7 @@ fn read_file_type_regular_file() {
assert_eq!(eval(&expr), Value::String("regular".to_string())); assert_eq!(eval(&expr), Value::String("regular".to_string()));
} }
#[test] #[test_log::test]
fn read_file_type_directory() { fn read_file_type_directory() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let test_dir = temp_dir.path().join("testdir"); let test_dir = temp_dir.path().join("testdir");
@@ -278,7 +278,7 @@ fn read_file_type_directory() {
assert_eq!(eval(&expr), Value::String("directory".to_string())); assert_eq!(eval(&expr), Value::String("directory".to_string()));
} }
#[test] #[test_log::test]
fn read_file_type_symlink() { fn read_file_type_symlink() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let target = temp_dir.path().join("target.txt"); let target = temp_dir.path().join("target.txt");
@@ -296,7 +296,7 @@ fn read_file_type_symlink() {
} }
} }
#[test] #[test_log::test]
fn read_dir_basic() { fn read_dir_basic() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let test_dir = temp_dir.path().join("readdir_test"); let test_dir = temp_dir.path().join("readdir_test");
@@ -328,7 +328,7 @@ fn read_dir_basic() {
} }
} }
#[test] #[test_log::test]
fn read_dir_empty() { fn read_dir_empty() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let test_dir = temp_dir.path().join("empty_dir"); let test_dir = temp_dir.path().join("empty_dir");
@@ -344,7 +344,7 @@ fn read_dir_empty() {
} }
} }
#[test] #[test_log::test]
fn read_dir_nonexistent_fails() { fn read_dir_nonexistent_fails() {
let expr = r#"builtins.readDir "/nonexistent/directory""#; let expr = r#"builtins.readDir "/nonexistent/directory""#;
let result = eval_result(expr); let result = eval_result(expr);
@@ -352,7 +352,7 @@ fn read_dir_nonexistent_fails() {
assert!(result.is_err()); assert!(result.is_err());
} }
#[test] #[test_log::test]
fn read_dir_on_file_fails() { fn read_dir_on_file_fails() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let test_file = temp_dir.path().join("test.txt"); let test_file = temp_dir.path().join("test.txt");

View File

@@ -42,7 +42,7 @@ fn format_value(value: &Value) -> String {
macro_rules! eval_okay_test { macro_rules! eval_okay_test {
($(#[$attr:meta])* $name:ident$(, $pre:expr)?) => { ($(#[$attr:meta])* $name:ident$(, $pre:expr)?) => {
$(#[$attr])* $(#[$attr])*
#[test] #[test_log::test]
fn $name() { fn $name() {
$(($pre)();)? $(($pre)();)?
let test_name = concat!("eval-okay-", stringify!($name)) let test_name = concat!("eval-okay-", stringify!($name))
@@ -74,7 +74,7 @@ macro_rules! eval_okay_test {
macro_rules! eval_fail_test { macro_rules! eval_fail_test {
($name:ident) => { ($name:ident) => {
#[test] #[test_log::test]
fn $name() { fn $name() {
let test_name = concat!("eval-fail-", stringify!($name)) let test_name = concat!("eval-fail-", stringify!($name))
.replace("_", "-") .replace("_", "-")

View File

@@ -1,12 +1,12 @@
use crate::utils::eval; use crate::utils::eval;
use nix_js::value::Value; use nix_js::value::Value;
#[test] #[test_log::test]
fn large_i64_max() { fn large_i64_max() {
assert_eq!(eval("9223372036854775807"), Value::Int(9223372036854775807)); assert_eq!(eval("9223372036854775807"), Value::Int(9223372036854775807));
} }
#[test] #[test_log::test]
fn large_i64_negative() { fn large_i64_negative() {
assert_eq!( assert_eq!(
eval("-9223372036854775807"), eval("-9223372036854775807"),
@@ -14,7 +14,7 @@ fn large_i64_negative() {
); );
} }
#[test] #[test_log::test]
fn large_number_arithmetic() { fn large_number_arithmetic() {
assert_eq!( assert_eq!(
eval("5000000000000000000 + 3000000000000000000"), eval("5000000000000000000 + 3000000000000000000"),
@@ -22,33 +22,33 @@ fn large_number_arithmetic() {
); );
} }
#[test] #[test_log::test]
fn is_int_with_int() { fn is_int_with_int() {
assert_eq!(eval("builtins.isInt 42"), Value::Bool(true)); assert_eq!(eval("builtins.isInt 42"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn is_int_with_float() { fn is_int_with_float() {
assert_eq!(eval("builtins.isInt 42.0"), Value::Bool(false)); assert_eq!(eval("builtins.isInt 42.0"), Value::Bool(false));
} }
#[test] #[test_log::test]
fn is_float_with_int() { fn is_float_with_int() {
assert_eq!(eval("builtins.isFloat 42"), Value::Bool(false)); assert_eq!(eval("builtins.isFloat 42"), Value::Bool(false));
} }
#[test] #[test_log::test]
fn is_float_with_float() { fn is_float_with_float() {
assert_eq!(eval("builtins.isFloat 42.5"), Value::Bool(true)); assert_eq!(eval("builtins.isFloat 42.5"), Value::Bool(true));
assert_eq!(eval("builtins.isFloat 1.0"), Value::Bool(true)); assert_eq!(eval("builtins.isFloat 1.0"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn typeof_int() { fn typeof_int() {
assert_eq!(eval("builtins.typeOf 1"), Value::String("int".to_string())); assert_eq!(eval("builtins.typeOf 1"), Value::String("int".to_string()));
} }
#[test] #[test_log::test]
fn typeof_float() { fn typeof_float() {
assert_eq!( assert_eq!(
eval("builtins.typeOf 1.0"), eval("builtins.typeOf 1.0"),
@@ -60,17 +60,17 @@ fn typeof_float() {
); );
} }
#[test] #[test_log::test]
fn int_literal() { fn int_literal() {
assert_eq!(eval("1"), Value::Int(1)); assert_eq!(eval("1"), Value::Int(1));
} }
#[test] #[test_log::test]
fn float_literal() { fn float_literal() {
assert_eq!(eval("1."), Value::Float(1.)); assert_eq!(eval("1."), Value::Float(1.));
} }
#[test] #[test_log::test]
fn int_plus_int() { fn int_plus_int() {
assert_eq!( assert_eq!(
eval("builtins.typeOf (1 + 2)"), eval("builtins.typeOf (1 + 2)"),
@@ -78,7 +78,7 @@ fn int_plus_int() {
); );
} }
#[test] #[test_log::test]
fn int_plus_float() { fn int_plus_float() {
assert_eq!( assert_eq!(
eval("builtins.typeOf (1 + 2.0)"), eval("builtins.typeOf (1 + 2.0)"),
@@ -86,7 +86,7 @@ fn int_plus_float() {
); );
} }
#[test] #[test_log::test]
fn int_times_int() { fn int_times_int() {
assert_eq!( assert_eq!(
eval("builtins.typeOf (3 * 4)"), eval("builtins.typeOf (3 * 4)"),
@@ -94,7 +94,7 @@ fn int_times_int() {
); );
} }
#[test] #[test_log::test]
fn int_times_float() { fn int_times_float() {
assert_eq!( assert_eq!(
eval("builtins.typeOf (3 * 4.0)"), eval("builtins.typeOf (3 * 4.0)"),
@@ -102,25 +102,25 @@ fn int_times_float() {
); );
} }
#[test] #[test_log::test]
fn integer_division() { fn integer_division() {
assert_eq!(eval("5 / 2"), Value::Int(2)); assert_eq!(eval("5 / 2"), Value::Int(2));
assert_eq!(eval("7 / 3"), Value::Int(2)); assert_eq!(eval("7 / 3"), Value::Int(2));
assert_eq!(eval("10 / 3"), Value::Int(3)); assert_eq!(eval("10 / 3"), Value::Int(3));
} }
#[test] #[test_log::test]
fn float_division() { fn float_division() {
assert_eq!(eval("5 / 2.0"), Value::Float(2.5)); assert_eq!(eval("5 / 2.0"), Value::Float(2.5));
assert_eq!(eval("7.0 / 2"), Value::Float(3.5)); assert_eq!(eval("7.0 / 2"), Value::Float(3.5));
} }
#[test] #[test_log::test]
fn negative_integer_division() { fn negative_integer_division() {
assert_eq!(eval("(-7) / 3"), Value::Int(-2)); assert_eq!(eval("(-7) / 3"), Value::Int(-2));
} }
#[test] #[test_log::test]
fn builtin_add_with_large_numbers() { fn builtin_add_with_large_numbers() {
assert_eq!( assert_eq!(
eval("builtins.add 5000000000000000000 3000000000000000000"), eval("builtins.add 5000000000000000000 3000000000000000000"),
@@ -128,7 +128,7 @@ fn builtin_add_with_large_numbers() {
); );
} }
#[test] #[test_log::test]
fn builtin_mul_with_large_numbers() { fn builtin_mul_with_large_numbers() {
assert_eq!( assert_eq!(
eval("builtins.mul 1000000000 1000000000"), eval("builtins.mul 1000000000 1000000000"),

View File

@@ -2,67 +2,67 @@ use crate::utils::eval;
use nix_js::value::{AttrSet, List, Symbol, Value}; use nix_js::value::{AttrSet, List, Symbol, Value};
use std::collections::BTreeMap; use std::collections::BTreeMap;
#[test] #[test_log::test]
fn addition() { fn addition() {
assert_eq!(eval("1 + 1"), Value::Int(2)); assert_eq!(eval("1 + 1"), Value::Int(2));
} }
#[test] #[test_log::test]
fn subtraction() { fn subtraction() {
assert_eq!(eval("2 - 1"), Value::Int(1)); assert_eq!(eval("2 - 1"), Value::Int(1));
} }
#[test] #[test_log::test]
fn multiplication() { fn multiplication() {
assert_eq!(eval("1. * 1"), Value::Float(1.)); assert_eq!(eval("1. * 1"), Value::Float(1.));
} }
#[test] #[test_log::test]
fn division() { fn division() {
assert_eq!(eval("1 / 1."), Value::Float(1.)); assert_eq!(eval("1 / 1."), Value::Float(1.));
} }
#[test] #[test_log::test]
fn equality() { fn equality() {
assert_eq!(eval("1 == 1"), Value::Bool(true)); assert_eq!(eval("1 == 1"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn inequality() { fn inequality() {
assert_eq!(eval("1 != 1"), Value::Bool(false)); assert_eq!(eval("1 != 1"), Value::Bool(false));
} }
#[test] #[test_log::test]
fn less_than() { fn less_than() {
assert_eq!(eval("2 < 1"), Value::Bool(false)); assert_eq!(eval("2 < 1"), Value::Bool(false));
} }
#[test] #[test_log::test]
fn greater_than() { fn greater_than() {
assert_eq!(eval("2 > 1"), Value::Bool(true)); assert_eq!(eval("2 > 1"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn less_than_or_equal() { fn less_than_or_equal() {
assert_eq!(eval("1 <= 1"), Value::Bool(true)); assert_eq!(eval("1 <= 1"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn greater_than_or_equal() { fn greater_than_or_equal() {
assert_eq!(eval("1 >= 1"), Value::Bool(true)); assert_eq!(eval("1 >= 1"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn logical_or_short_circuit() { fn logical_or_short_circuit() {
assert_eq!(eval("true || (1 / 0)"), Value::Bool(true)); assert_eq!(eval("true || (1 / 0)"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn logical_and() { fn logical_and() {
assert_eq!(eval("true && 1 == 0"), Value::Bool(false)); assert_eq!(eval("true && 1 == 0"), Value::Bool(false));
} }
#[test] #[test_log::test]
fn list_concatenation() { fn list_concatenation() {
assert_eq!( assert_eq!(
eval("[ 1 2 3 ] ++ [ 4 5 6 ]"), eval("[ 1 2 3 ] ++ [ 4 5 6 ]"),
@@ -70,7 +70,7 @@ fn list_concatenation() {
); );
} }
#[test] #[test_log::test]
fn attrset_update() { fn attrset_update() {
assert_eq!( assert_eq!(
eval("{ a.b = 1; b = 2; } // { a.c = 2; }"), eval("{ a.b = 1; b = 2; } // { a.c = 2; }"),
@@ -87,23 +87,23 @@ fn attrset_update() {
); );
} }
#[test] #[test_log::test]
fn unary_negation() { fn unary_negation() {
assert_eq!(eval("-5"), Value::Int(-5)); assert_eq!(eval("-5"), Value::Int(-5));
} }
#[test] #[test_log::test]
fn logical_not() { fn logical_not() {
assert_eq!(eval("!true"), Value::Bool(false)); assert_eq!(eval("!true"), Value::Bool(false));
assert_eq!(eval("!false"), Value::Bool(true)); assert_eq!(eval("!false"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn select_with_default_lazy_evaluation() { fn select_with_default_lazy_evaluation() {
assert_eq!(eval("{ a = 1; }.a or (1 / 0)"), Value::Int(1)); assert_eq!(eval("{ a = 1; }.a or (1 / 0)"), Value::Int(1));
} }
#[test] #[test_log::test]
fn select_with_default_nested_lazy() { fn select_with_default_nested_lazy() {
assert_eq!( assert_eq!(
eval("{ a.b = 42; }.a.b or (builtins.abort \"should not evaluate\")"), eval("{ a.b = 42; }.a.b or (builtins.abort \"should not evaluate\")"),
@@ -111,32 +111,32 @@ fn select_with_default_nested_lazy() {
); );
} }
#[test] #[test_log::test]
fn select_with_default_fallback() { fn select_with_default_fallback() {
assert_eq!(eval("{ a = 1; }.b or 999"), Value::Int(999)); assert_eq!(eval("{ a = 1; }.b or 999"), Value::Int(999));
} }
#[test] #[test_log::test]
fn implication_false_false() { fn implication_false_false() {
assert_eq!(eval("false -> false"), Value::Bool(true)); assert_eq!(eval("false -> false"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn implication_false_true() { fn implication_false_true() {
assert_eq!(eval("false -> true"), Value::Bool(true)); assert_eq!(eval("false -> true"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn implication_true_false() { fn implication_true_false() {
assert_eq!(eval("true -> false"), Value::Bool(false)); assert_eq!(eval("true -> false"), Value::Bool(false));
} }
#[test] #[test_log::test]
fn implication_true_true() { fn implication_true_true() {
assert_eq!(eval("true -> true"), Value::Bool(true)); assert_eq!(eval("true -> true"), Value::Bool(true));
} }
#[test] #[test_log::test]
fn implication_short_circuit() { fn implication_short_circuit() {
assert_eq!(eval("false -> (1 / 0)"), Value::Bool(true)); assert_eq!(eval("false -> (1 / 0)"), Value::Bool(true));
} }

View File

@@ -1,113 +1,113 @@
use crate::utils::{eval, eval_result}; use crate::utils::{eval, eval_result};
use nix_js::value::Value; use nix_js::value::Value;
#[test] #[test_log::test]
fn path_type_of() { fn path_type_of() {
let result = eval("builtins.typeOf ./foo"); let result = eval("builtins.typeOf ./foo");
assert_eq!(result, Value::String("path".to_string())); assert_eq!(result, Value::String("path".to_string()));
} }
#[test] #[test_log::test]
fn is_path_true() { fn is_path_true() {
let result = eval("builtins.isPath ./foo"); let result = eval("builtins.isPath ./foo");
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
fn is_path_false_string() { fn is_path_false_string() {
let result = eval(r#"builtins.isPath "./foo""#); let result = eval(r#"builtins.isPath "./foo""#);
assert_eq!(result, Value::Bool(false)); assert_eq!(result, Value::Bool(false));
} }
#[test] #[test_log::test]
fn is_path_false_number() { fn is_path_false_number() {
let result = eval("builtins.isPath 42"); let result = eval("builtins.isPath 42");
assert_eq!(result, Value::Bool(false)); assert_eq!(result, Value::Bool(false));
} }
#[test] #[test_log::test]
fn path_concat_type() { fn path_concat_type() {
// path + string = path // path + string = path
let result = eval(r#"builtins.typeOf (./foo + "/bar")"#); let result = eval(r#"builtins.typeOf (./foo + "/bar")"#);
assert_eq!(result, Value::String("path".to_string())); assert_eq!(result, Value::String("path".to_string()));
} }
#[test] #[test_log::test]
fn string_path_concat_type() { fn string_path_concat_type() {
// string + path = string // string + path = string
let result = eval(r#"builtins.typeOf ("prefix-" + ./foo)"#); let result = eval(r#"builtins.typeOf ("prefix-" + ./foo)"#);
assert_eq!(result, Value::String("string".to_string())); assert_eq!(result, Value::String("string".to_string()));
} }
#[test] #[test_log::test]
fn basename_of_path() { fn basename_of_path() {
let result = eval("builtins.baseNameOf ./path/to/file.nix"); let result = eval("builtins.baseNameOf ./path/to/file.nix");
assert!(matches!(result, Value::String(s) if s == "file.nix")); assert!(matches!(result, Value::String(s) if s == "file.nix"));
} }
#[test] #[test_log::test]
fn basename_of_string() { fn basename_of_string() {
let result = eval(r#"builtins.baseNameOf "/path/to/file.nix""#); let result = eval(r#"builtins.baseNameOf "/path/to/file.nix""#);
assert_eq!(result, Value::String("file.nix".to_string())); assert_eq!(result, Value::String("file.nix".to_string()));
} }
#[test] #[test_log::test]
fn dir_of_path_type() { fn dir_of_path_type() {
// dirOf preserves path type // dirOf preserves path type
let result = eval("builtins.typeOf (builtins.dirOf ./path/to/file.nix)"); let result = eval("builtins.typeOf (builtins.dirOf ./path/to/file.nix)");
assert_eq!(result, Value::String("path".to_string())); assert_eq!(result, Value::String("path".to_string()));
} }
#[test] #[test_log::test]
fn dir_of_string_type() { fn dir_of_string_type() {
// dirOf preserves string type // dirOf preserves string type
let result = eval(r#"builtins.typeOf (builtins.dirOf "/path/to/file.nix")"#); let result = eval(r#"builtins.typeOf (builtins.dirOf "/path/to/file.nix")"#);
assert_eq!(result, Value::String("string".to_string())); assert_eq!(result, Value::String("string".to_string()));
} }
#[test] #[test_log::test]
fn path_equality() { fn path_equality() {
// Same path should be equal // Same path should be equal
let result = eval("./foo == ./foo"); let result = eval("./foo == ./foo");
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
fn path_not_equal_string() { fn path_not_equal_string() {
// Paths and strings are different types - should not be equal // Paths and strings are different types - should not be equal
let result = eval(r#"./foo == "./foo""#); let result = eval(r#"./foo == "./foo""#);
assert_eq!(result, Value::Bool(false)); assert_eq!(result, Value::Bool(false));
} }
#[test] #[test_log::test]
fn to_path_absolute() { fn to_path_absolute() {
// toPath with absolute path returns string // toPath with absolute path returns string
let result = eval(r#"builtins.toPath "/foo/bar""#); let result = eval(r#"builtins.toPath "/foo/bar""#);
assert_eq!(result, Value::String("/foo/bar".to_string())); assert_eq!(result, Value::String("/foo/bar".to_string()));
} }
#[test] #[test_log::test]
fn to_path_type_is_string() { fn to_path_type_is_string() {
// toPath returns a string, not a path // toPath returns a string, not a path
let result = eval(r#"builtins.typeOf (builtins.toPath "/foo")"#); let result = eval(r#"builtins.typeOf (builtins.toPath "/foo")"#);
assert_eq!(result, Value::String("string".to_string())); assert_eq!(result, Value::String("string".to_string()));
} }
#[test] #[test_log::test]
fn to_path_relative_fails() { fn to_path_relative_fails() {
// toPath with relative path should fail // toPath with relative path should fail
let result = eval_result(r#"builtins.toPath "foo/bar""#); let result = eval_result(r#"builtins.toPath "foo/bar""#);
assert!(result.is_err()); assert!(result.is_err());
} }
#[test] #[test_log::test]
fn to_path_empty_fails() { fn to_path_empty_fails() {
// toPath with empty string should fail // toPath with empty string should fail
let result = eval_result(r#"builtins.toPath """#); let result = eval_result(r#"builtins.toPath """#);
assert!(result.is_err()); assert!(result.is_err());
} }
#[test] #[test_log::test]
fn to_path_from_path_value() { fn to_path_from_path_value() {
// toPath can accept a path value too (coerces to string first) // toPath can accept a path value too (coerces to string first)
let result = eval("builtins.toPath ./foo"); let result = eval("builtins.toPath ./foo");

View File

@@ -3,7 +3,7 @@ use nix_js::value::{List, Value};
use crate::utils::eval_result; use crate::utils::eval_result;
#[test] #[test_log::test]
fn match_exact_full_string() { fn match_exact_full_string() {
assert_eq!( assert_eq!(
eval(r#"builtins.match "foobar" "foobar""#), eval(r#"builtins.match "foobar" "foobar""#),
@@ -11,12 +11,12 @@ fn match_exact_full_string() {
); );
} }
#[test] #[test_log::test]
fn match_partial_returns_null() { fn match_partial_returns_null() {
assert_eq!(eval(r#"builtins.match "foo" "foobar""#), Value::Null); assert_eq!(eval(r#"builtins.match "foo" "foobar""#), Value::Null);
} }
#[test] #[test_log::test]
fn match_with_capture_groups() { fn match_with_capture_groups() {
assert_eq!( assert_eq!(
eval(r#"builtins.match "(.*)\\.nix" "foobar.nix""#), eval(r#"builtins.match "(.*)\\.nix" "foobar.nix""#),
@@ -24,7 +24,7 @@ fn match_with_capture_groups() {
); );
} }
#[test] #[test_log::test]
fn match_multiple_capture_groups() { fn match_multiple_capture_groups() {
assert_eq!( assert_eq!(
eval(r#"builtins.match "((.*)/)?([^/]*)\\.nix" "foobar.nix""#), eval(r#"builtins.match "((.*)/)?([^/]*)\\.nix" "foobar.nix""#),
@@ -36,7 +36,7 @@ fn match_multiple_capture_groups() {
); );
} }
#[test] #[test_log::test]
fn match_with_path() { fn match_with_path() {
assert_eq!( assert_eq!(
eval(r#"builtins.match "((.*)/)?([^/]*)\\.nix" "/path/to/foobar.nix""#), eval(r#"builtins.match "((.*)/)?([^/]*)\\.nix" "/path/to/foobar.nix""#),
@@ -48,7 +48,7 @@ fn match_with_path() {
); );
} }
#[test] #[test_log::test]
fn match_posix_space_class() { fn match_posix_space_class() {
assert_eq!( assert_eq!(
eval(r#"builtins.match "[[:space:]]+([^[:space:]]+)[[:space:]]+" " foo ""#), eval(r#"builtins.match "[[:space:]]+([^[:space:]]+)[[:space:]]+" " foo ""#),
@@ -56,7 +56,7 @@ fn match_posix_space_class() {
); );
} }
#[test] #[test_log::test]
fn match_posix_upper_class() { fn match_posix_upper_class() {
assert_eq!( assert_eq!(
eval(r#"builtins.match "[[:space:]]+([[:upper:]]+)[[:space:]]+" " foo ""#), eval(r#"builtins.match "[[:space:]]+([[:upper:]]+)[[:space:]]+" " foo ""#),
@@ -69,7 +69,7 @@ fn match_posix_upper_class() {
); );
} }
#[test] #[test_log::test]
fn match_quantifiers() { fn match_quantifiers() {
assert_eq!( assert_eq!(
eval(r#"builtins.match "fo*" "f""#), eval(r#"builtins.match "fo*" "f""#),
@@ -86,7 +86,7 @@ fn match_quantifiers() {
assert_eq!(eval(r#"builtins.match "fo{1,2}" "fooo""#), Value::Null); assert_eq!(eval(r#"builtins.match "fo{1,2}" "fooo""#), Value::Null);
} }
#[test] #[test_log::test]
fn split_non_capturing() { fn split_non_capturing() {
assert_eq!( assert_eq!(
eval(r#"builtins.split "foobar" "foobar""#), eval(r#"builtins.split "foobar" "foobar""#),
@@ -98,7 +98,7 @@ fn split_non_capturing() {
); );
} }
#[test] #[test_log::test]
fn split_no_match() { fn split_no_match() {
assert_eq!( assert_eq!(
eval(r#"builtins.split "fo+" "f""#), eval(r#"builtins.split "fo+" "f""#),
@@ -106,7 +106,7 @@ fn split_no_match() {
); );
} }
#[test] #[test_log::test]
fn split_with_capture_group() { fn split_with_capture_group() {
assert_eq!( assert_eq!(
eval(r#"builtins.split "(fo*)" "foobar""#), eval(r#"builtins.split "(fo*)" "foobar""#),
@@ -118,7 +118,7 @@ fn split_with_capture_group() {
); );
} }
#[test] #[test_log::test]
fn split_multiple_matches() { fn split_multiple_matches() {
assert_eq!( assert_eq!(
eval(r#"builtins.split "(b)" "foobarbaz""#), eval(r#"builtins.split "(b)" "foobarbaz""#),
@@ -132,7 +132,7 @@ fn split_multiple_matches() {
); );
} }
#[test] #[test_log::test]
fn split_with_multiple_groups() { fn split_with_multiple_groups() {
assert_eq!( assert_eq!(
eval(r#"builtins.split "(f)(o*)" "foo""#), eval(r#"builtins.split "(f)(o*)" "foo""#),
@@ -147,7 +147,7 @@ fn split_with_multiple_groups() {
); );
} }
#[test] #[test_log::test]
fn split_with_optional_groups() { fn split_with_optional_groups() {
assert_eq!( assert_eq!(
eval(r#"builtins.split "(a)|(c)" "abc""#), eval(r#"builtins.split "(a)|(c)" "abc""#),
@@ -161,7 +161,7 @@ fn split_with_optional_groups() {
); );
} }
#[test] #[test_log::test]
fn split_greedy_matching() { fn split_greedy_matching() {
assert_eq!( assert_eq!(
eval(r#"builtins.split "(o+)" "oooofoooo""#), eval(r#"builtins.split "(o+)" "oooofoooo""#),
@@ -175,7 +175,7 @@ fn split_greedy_matching() {
); );
} }
#[test] #[test_log::test]
fn split_posix_classes() { fn split_posix_classes() {
assert_eq!( assert_eq!(
eval(r#"builtins.split "([[:upper:]]+)" " FOO ""#), eval(r#"builtins.split "([[:upper:]]+)" " FOO ""#),
@@ -187,7 +187,7 @@ fn split_posix_classes() {
); );
} }
#[test] #[test_log::test]
fn replace_basic() { fn replace_basic() {
assert_eq!( assert_eq!(
eval(r#"builtins.replaceStrings ["o"] ["a"] "foobar""#), eval(r#"builtins.replaceStrings ["o"] ["a"] "foobar""#),
@@ -195,7 +195,7 @@ fn replace_basic() {
); );
} }
#[test] #[test_log::test]
fn replace_with_empty() { fn replace_with_empty() {
assert_eq!( assert_eq!(
eval(r#"builtins.replaceStrings ["o"] [""] "foobar""#), eval(r#"builtins.replaceStrings ["o"] [""] "foobar""#),
@@ -203,7 +203,7 @@ fn replace_with_empty() {
); );
} }
#[test] #[test_log::test]
fn replace_multiple_patterns() { fn replace_multiple_patterns() {
assert_eq!( assert_eq!(
eval(r#"builtins.replaceStrings ["oo" "a"] ["a" "oo"] "foobar""#), eval(r#"builtins.replaceStrings ["oo" "a"] ["a" "oo"] "foobar""#),
@@ -211,7 +211,7 @@ fn replace_multiple_patterns() {
); );
} }
#[test] #[test_log::test]
fn replace_first_match_wins() { fn replace_first_match_wins() {
assert_eq!( assert_eq!(
eval(r#"builtins.replaceStrings ["oo" "oo"] ["u" "i"] "foobar""#), eval(r#"builtins.replaceStrings ["oo" "oo"] ["u" "i"] "foobar""#),
@@ -219,7 +219,7 @@ fn replace_first_match_wins() {
); );
} }
#[test] #[test_log::test]
fn replace_empty_pattern() { fn replace_empty_pattern() {
assert_eq!( assert_eq!(
eval(r#"builtins.replaceStrings [""] ["X"] "abc""#), eval(r#"builtins.replaceStrings [""] ["X"] "abc""#),
@@ -227,7 +227,7 @@ fn replace_empty_pattern() {
); );
} }
#[test] #[test_log::test]
fn replace_empty_pattern_empty_string() { fn replace_empty_pattern_empty_string() {
assert_eq!( assert_eq!(
eval(r#"builtins.replaceStrings [""] ["X"] """#), eval(r#"builtins.replaceStrings [""] ["X"] """#),
@@ -235,7 +235,7 @@ fn replace_empty_pattern_empty_string() {
); );
} }
#[test] #[test_log::test]
fn replace_simple_char() { fn replace_simple_char() {
assert_eq!( assert_eq!(
eval(r#"builtins.replaceStrings ["-"] ["_"] "a-b""#), eval(r#"builtins.replaceStrings ["-"] ["_"] "a-b""#),
@@ -243,7 +243,7 @@ fn replace_simple_char() {
); );
} }
#[test] #[test_log::test]
fn replace_longer_pattern() { fn replace_longer_pattern() {
assert_eq!( assert_eq!(
eval(r#"builtins.replaceStrings ["oo"] ["u"] "foobar""#), eval(r#"builtins.replaceStrings ["oo"] ["u"] "foobar""#),
@@ -251,13 +251,13 @@ fn replace_longer_pattern() {
); );
} }
#[test] #[test_log::test]
fn replace_different_lengths() { fn replace_different_lengths() {
let result = eval_result(r#"builtins.replaceStrings ["a" "b"] ["x"] "test""#); let result = eval_result(r#"builtins.replaceStrings ["a" "b"] ["x"] "test""#);
assert!(result.is_err()); assert!(result.is_err());
} }
#[test] #[test_log::test]
fn split_version_simple() { fn split_version_simple() {
assert_eq!( assert_eq!(
eval(r#"builtins.splitVersion "1.2.3""#), eval(r#"builtins.splitVersion "1.2.3""#),
@@ -269,7 +269,7 @@ fn split_version_simple() {
); );
} }
#[test] #[test_log::test]
fn split_version_with_pre() { fn split_version_with_pre() {
assert_eq!( assert_eq!(
eval(r#"builtins.splitVersion "2.3.0pre1234""#), eval(r#"builtins.splitVersion "2.3.0pre1234""#),
@@ -283,7 +283,7 @@ fn split_version_with_pre() {
); );
} }
#[test] #[test_log::test]
fn split_version_with_letters() { fn split_version_with_letters() {
assert_eq!( assert_eq!(
eval(r#"builtins.splitVersion "2.3a""#), eval(r#"builtins.splitVersion "2.3a""#),
@@ -295,7 +295,7 @@ fn split_version_with_letters() {
); );
} }
#[test] #[test_log::test]
fn split_version_with_dashes() { fn split_version_with_dashes() {
assert_eq!( assert_eq!(
eval(r#"builtins.splitVersion "2.3-beta1""#), eval(r#"builtins.splitVersion "2.3-beta1""#),
@@ -308,7 +308,7 @@ fn split_version_with_dashes() {
); );
} }
#[test] #[test_log::test]
fn split_version_empty() { fn split_version_empty() {
assert_eq!( assert_eq!(
eval(r#"builtins.splitVersion """#), eval(r#"builtins.splitVersion """#),

View File

@@ -6,13 +6,13 @@ fn eval(expr: &str) -> Value {
eval_result(expr).unwrap_or_else(|e| panic!("{}", e)) eval_result(expr).unwrap_or_else(|e| panic!("{}", e))
} }
#[test] #[test_log::test]
fn hascontext_plain_string() { fn hascontext_plain_string() {
let result = eval(r#"builtins.hasContext "hello""#); let result = eval(r#"builtins.hasContext "hello""#);
assert_eq!(result, Value::Bool(false)); assert_eq!(result, Value::Bool(false));
} }
#[test] #[test_log::test]
fn hascontext_derivation_output() { fn hascontext_derivation_output() {
let result = eval( let result = eval(
r#" r#"
@@ -24,7 +24,7 @@ fn hascontext_derivation_output() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
fn getcontext_plain_string() { fn getcontext_plain_string() {
let result = eval(r#"builtins.getContext "hello""#); let result = eval(r#"builtins.getContext "hello""#);
match result { match result {
@@ -35,7 +35,7 @@ fn getcontext_plain_string() {
} }
} }
#[test] #[test_log::test]
fn getcontext_derivation_output() { fn getcontext_derivation_output() {
let result = eval( let result = eval(
r#" r#"
@@ -60,7 +60,7 @@ fn getcontext_derivation_output() {
} }
} }
#[test] #[test_log::test]
fn unsafediscardstringcontext() { fn unsafediscardstringcontext() {
let result = eval( let result = eval(
r#" r#"
@@ -74,7 +74,7 @@ fn unsafediscardstringcontext() {
assert_eq!(result, Value::Bool(false)); assert_eq!(result, Value::Bool(false));
} }
#[test] #[test_log::test]
fn unsafediscardstringcontext_preserves_value() { fn unsafediscardstringcontext_preserves_value() {
let result = eval( let result = eval(
r#" r#"
@@ -88,7 +88,7 @@ fn unsafediscardstringcontext_preserves_value() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
fn appendcontext_basic() { fn appendcontext_basic() {
let result = eval( let result = eval(
r#" r#"
@@ -102,7 +102,7 @@ fn appendcontext_basic() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
fn appendcontext_preserves_value() { fn appendcontext_preserves_value() {
let result = eval( let result = eval(
r#" r#"
@@ -116,7 +116,7 @@ fn appendcontext_preserves_value() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
fn string_concat_merges_context() { fn string_concat_merges_context() {
let result = eval( let result = eval(
r#" r#"
@@ -133,7 +133,7 @@ fn string_concat_merges_context() {
assert_eq!(result, Value::Int(2)); assert_eq!(result, Value::Int(2));
} }
#[test] #[test_log::test]
fn string_add_merges_context() { fn string_add_merges_context() {
let result = eval( let result = eval(
r#" r#"
@@ -150,7 +150,7 @@ fn string_add_merges_context() {
assert_eq!(result, Value::Int(2)); assert_eq!(result, Value::Int(2));
} }
#[test] #[test_log::test]
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
@@ -179,7 +179,7 @@ fn context_in_derivation_args() {
} }
} }
#[test] #[test_log::test]
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
@@ -208,7 +208,7 @@ fn context_in_derivation_env() {
} }
} }
#[test] #[test_log::test]
fn tostring_preserves_context() { fn tostring_preserves_context() {
let result = eval( let result = eval(
r#" r#"
@@ -221,7 +221,7 @@ fn tostring_preserves_context() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
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
@@ -244,7 +244,7 @@ fn interpolation_derivation_returns_outpath() {
} }
} }
#[test] #[test_log::test]
fn interpolation_derivation_has_context() { fn interpolation_derivation_has_context() {
let result = eval( let result = eval(
r#" r#"
@@ -256,7 +256,7 @@ fn interpolation_derivation_has_context() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
fn interpolation_derivation_context_correct() { fn interpolation_derivation_context_correct() {
let result = eval( let result = eval(
r#" r#"
@@ -277,7 +277,7 @@ fn interpolation_derivation_context_correct() {
} }
} }
#[test] #[test_log::test]
fn interpolation_multiple_derivations() { fn interpolation_multiple_derivations() {
let result = eval( let result = eval(
r#" r#"
@@ -292,7 +292,7 @@ fn interpolation_multiple_derivations() {
assert_eq!(result, Value::Int(2)); assert_eq!(result, Value::Int(2));
} }
#[test] #[test_log::test]
fn interpolation_derivation_equals_tostring() { fn interpolation_derivation_equals_tostring() {
let result = eval( let result = eval(
r#" r#"
@@ -304,7 +304,7 @@ fn interpolation_derivation_equals_tostring() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
fn substring_preserves_context() { fn substring_preserves_context() {
let result = eval( let result = eval(
r#" r#"
@@ -318,7 +318,7 @@ fn substring_preserves_context() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
fn substring_zero_length_preserves_context() { fn substring_zero_length_preserves_context() {
let result = eval( let result = eval(
r#" r#"
@@ -332,7 +332,7 @@ fn substring_zero_length_preserves_context() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
fn substring_zero_length_empty_value() { fn substring_zero_length_empty_value() {
let result = eval( let result = eval(
r#" r#"
@@ -346,7 +346,7 @@ fn substring_zero_length_empty_value() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn concatStringsSep_preserves_context() { fn concatStringsSep_preserves_context() {
let result = eval( let result = eval(
@@ -363,7 +363,7 @@ fn concatStringsSep_preserves_context() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn concatStringsSep_merges_contexts() { fn concatStringsSep_merges_contexts() {
let result = eval( let result = eval(
@@ -381,7 +381,7 @@ fn concatStringsSep_merges_contexts() {
assert_eq!(result, Value::Int(2)); assert_eq!(result, Value::Int(2));
} }
#[test] #[test_log::test]
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn concatStringsSep_separator_has_context() { fn concatStringsSep_separator_has_context() {
let result = eval( let result = eval(
@@ -396,7 +396,7 @@ fn concatStringsSep_separator_has_context() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn replaceStrings_input_context_preserved() { fn replaceStrings_input_context_preserved() {
let result = eval( let result = eval(
@@ -411,7 +411,7 @@ fn replaceStrings_input_context_preserved() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn replaceStrings_replacement_context_collected() { fn replaceStrings_replacement_context_collected() {
let result = eval( let result = eval(
@@ -426,7 +426,7 @@ fn replaceStrings_replacement_context_collected() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn replaceStrings_merges_contexts() { fn replaceStrings_merges_contexts() {
let result = eval( let result = eval(
@@ -444,7 +444,7 @@ fn replaceStrings_merges_contexts() {
assert_eq!(result, Value::Int(2)); assert_eq!(result, Value::Int(2));
} }
#[test] #[test_log::test]
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn replaceStrings_lazy_evaluation_context() { fn replaceStrings_lazy_evaluation_context() {
let result = eval( let result = eval(
@@ -459,7 +459,7 @@ fn replaceStrings_lazy_evaluation_context() {
assert_eq!(result, Value::Bool(false)); assert_eq!(result, Value::Bool(false));
} }
#[test] #[test_log::test]
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn baseNameOf_preserves_context() { fn baseNameOf_preserves_context() {
let result = eval( let result = eval(
@@ -474,7 +474,7 @@ fn baseNameOf_preserves_context() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
fn split_no_match_preserves_context() { fn split_no_match_preserves_context() {
let result = eval( let result = eval(
r#" r#"
@@ -488,7 +488,7 @@ fn split_no_match_preserves_context() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
fn builtins_path_has_context() { fn builtins_path_has_context() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let test_file = temp_dir.path().join("test.txt"); let test_file = temp_dir.path().join("test.txt");
@@ -502,7 +502,7 @@ fn builtins_path_has_context() {
assert_eq!(result, Value::Bool(true)); assert_eq!(result, Value::Bool(true));
} }
#[test] #[test_log::test]
fn builtins_path_context_tracked_in_structured_attrs_derivation() { fn builtins_path_context_tracked_in_structured_attrs_derivation() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let test_file = temp_dir.path().join("test-patch.txt"); let test_file = temp_dir.path().join("test-patch.txt");
@@ -532,7 +532,7 @@ fn builtins_path_context_tracked_in_structured_attrs_derivation() {
} }
} }
#[test] #[test_log::test]
fn builtins_path_context_tracked_in_non_structured_derivation() { fn builtins_path_context_tracked_in_non_structured_derivation() {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let test_file = temp_dir.path().join("dep.txt"); let test_file = temp_dir.path().join("dep.txt");

View File

@@ -1,12 +1,12 @@
use crate::utils::eval; use crate::utils::eval;
use nix_js::value::Value; use nix_js::value::Value;
#[test] #[test_log::test]
fn non_recursive_bindings() { fn non_recursive_bindings() {
assert_eq!(eval("let x = 1; y = 2; z = x + y; in z"), Value::Int(3)); assert_eq!(eval("let x = 1; y = 2; z = x + y; in z"), Value::Int(3));
} }
#[test] #[test_log::test]
fn non_recursive_multiple_bindings() { fn non_recursive_multiple_bindings() {
assert_eq!( assert_eq!(
eval("let a = 10; b = 20; c = 30; d = a + b + c; in d"), eval("let a = 10; b = 20; c = 30; d = a + b + c; in d"),
@@ -14,7 +14,7 @@ fn non_recursive_multiple_bindings() {
); );
} }
#[test] #[test_log::test]
fn recursive_fibonacci() { fn recursive_fibonacci() {
assert_eq!( assert_eq!(
eval("let fib = n: if n <= 1 then 1 else fib (n - 1) + fib (n - 2); in fib 5"), eval("let fib = n: if n <= 1 then 1 else fib (n - 1) + fib (n - 2); in fib 5"),
@@ -22,7 +22,7 @@ fn recursive_fibonacci() {
); );
} }
#[test] #[test_log::test]
fn recursive_factorial() { fn recursive_factorial() {
assert_eq!( assert_eq!(
eval("let factorial = n: if n == 0 then 1 else n * factorial (n - 1); in factorial 5"), eval("let factorial = n: if n == 0 then 1 else n * factorial (n - 1); in factorial 5"),
@@ -30,7 +30,7 @@ fn recursive_factorial() {
); );
} }
#[test] #[test_log::test]
fn mutual_recursion_simple() { fn mutual_recursion_simple() {
assert_eq!( assert_eq!(
eval( eval(
@@ -40,7 +40,7 @@ fn mutual_recursion_simple() {
); );
} }
#[test] #[test_log::test]
fn mutual_recursion_even_odd() { fn mutual_recursion_even_odd() {
assert_eq!( assert_eq!(
eval( eval(
@@ -50,7 +50,7 @@ fn mutual_recursion_even_odd() {
); );
} }
#[test] #[test_log::test]
fn mixed_recursive_and_non_recursive() { fn mixed_recursive_and_non_recursive() {
assert_eq!( assert_eq!(
eval("let x = 1; f = n: if n == 0 then x else f (n - 1); in f 5"), eval("let x = 1; f = n: if n == 0 then x else f (n - 1); in f 5"),
@@ -58,7 +58,7 @@ fn mixed_recursive_and_non_recursive() {
); );
} }
#[test] #[test_log::test]
fn mixed_with_multiple_non_recursive() { fn mixed_with_multiple_non_recursive() {
assert_eq!( assert_eq!(
eval( eval(
@@ -68,12 +68,12 @@ fn mixed_with_multiple_non_recursive() {
); );
} }
#[test] #[test_log::test]
fn rec_attrset_non_recursive() { fn rec_attrset_non_recursive() {
assert_eq!(eval("rec { x = 1; y = 2; z = x + y; }.z"), Value::Int(3)); assert_eq!(eval("rec { x = 1; y = 2; z = x + y; }.z"), Value::Int(3));
} }
#[test] #[test_log::test]
fn rec_attrset_recursive() { fn rec_attrset_recursive() {
assert_eq!( assert_eq!(
eval("rec { f = n: if n == 0 then 0 else f (n - 1); }.f 10"), eval("rec { f = n: if n == 0 then 0 else f (n - 1); }.f 10"),
@@ -81,7 +81,7 @@ fn rec_attrset_recursive() {
); );
} }
#[test] #[test_log::test]
fn nested_let_non_recursive() { fn nested_let_non_recursive() {
assert_eq!( assert_eq!(
eval("let x = 1; in let y = x + 1; z = y + 1; in z"), eval("let x = 1; in let y = x + 1; z = y + 1; in z"),
@@ -89,7 +89,7 @@ fn nested_let_non_recursive() {
); );
} }
#[test] #[test_log::test]
fn nested_let_with_recursive() { fn nested_let_with_recursive() {
assert_eq!( assert_eq!(
eval("let f = n: if n == 0 then 0 else f (n - 1); in let g = m: f m; in g 5"), eval("let f = n: if n == 0 then 0 else f (n - 1); in let g = m: f m; in g 5"),
@@ -97,7 +97,7 @@ fn nested_let_with_recursive() {
); );
} }
#[test] #[test_log::test]
fn three_way_mutual_recursion() { fn three_way_mutual_recursion() {
assert_eq!( assert_eq!(
eval( eval(
@@ -107,7 +107,7 @@ fn three_way_mutual_recursion() {
); );
} }
#[test] #[test_log::test]
fn complex_mixed_dependencies() { fn complex_mixed_dependencies() {
assert_eq!( assert_eq!(
eval( eval(

View File

@@ -1,7 +1,7 @@
use crate::utils::{eval, eval_result}; use crate::utils::{eval, eval_result};
use nix_js::value::Value; use nix_js::value::Value;
#[test] #[test_log::test]
fn string_returns_as_is() { fn string_returns_as_is() {
assert_eq!( assert_eq!(
eval(r#"toString "hello""#), eval(r#"toString "hello""#),
@@ -9,32 +9,32 @@ fn string_returns_as_is() {
); );
} }
#[test] #[test_log::test]
fn integer_to_string() { fn integer_to_string() {
assert_eq!(eval("toString 42"), Value::String("42".to_string())); assert_eq!(eval("toString 42"), Value::String("42".to_string()));
assert_eq!(eval("toString (-5)"), Value::String("-5".to_string())); assert_eq!(eval("toString (-5)"), Value::String("-5".to_string()));
assert_eq!(eval("toString 0"), Value::String("0".to_string())); assert_eq!(eval("toString 0"), Value::String("0".to_string()));
} }
#[test] #[test_log::test]
fn float_to_string() { fn float_to_string() {
assert_eq!(eval("toString 3.14"), Value::String("3.14".to_string())); assert_eq!(eval("toString 3.14"), Value::String("3.14".to_string()));
assert_eq!(eval("toString 0.0"), Value::String("0".to_string())); assert_eq!(eval("toString 0.0"), Value::String("0".to_string()));
assert_eq!(eval("toString (-2.5)"), Value::String("-2.5".to_string())); assert_eq!(eval("toString (-2.5)"), Value::String("-2.5".to_string()));
} }
#[test] #[test_log::test]
fn bool_to_string() { fn bool_to_string() {
assert_eq!(eval("toString true"), Value::String("1".to_string())); assert_eq!(eval("toString true"), Value::String("1".to_string()));
assert_eq!(eval("toString false"), Value::String("".to_string())); assert_eq!(eval("toString false"), Value::String("".to_string()));
} }
#[test] #[test_log::test]
fn null_to_string() { fn null_to_string() {
assert_eq!(eval("toString null"), Value::String("".to_string())); assert_eq!(eval("toString null"), Value::String("".to_string()));
} }
#[test] #[test_log::test]
fn simple_list_to_string() { fn simple_list_to_string() {
assert_eq!(eval("toString [1 2 3]"), Value::String("1 2 3".to_string())); assert_eq!(eval("toString [1 2 3]"), Value::String("1 2 3".to_string()));
assert_eq!( assert_eq!(
@@ -43,7 +43,7 @@ fn simple_list_to_string() {
); );
} }
#[test] #[test_log::test]
fn nested_list_flattens() { fn nested_list_flattens() {
assert_eq!( assert_eq!(
eval("toString [[1 2] [3 4]]"), eval("toString [[1 2] [3 4]]"),
@@ -55,14 +55,14 @@ fn nested_list_flattens() {
); );
} }
#[test] #[test_log::test]
fn empty_list_in_list_no_extra_space() { fn empty_list_in_list_no_extra_space() {
assert_eq!(eval("toString [1 [] 2]"), Value::String("1 2".to_string())); assert_eq!(eval("toString [1 [] 2]"), Value::String("1 2".to_string()));
assert_eq!(eval("toString [[] 1 2]"), Value::String("1 2".to_string())); assert_eq!(eval("toString [[] 1 2]"), Value::String("1 2".to_string()));
assert_eq!(eval("toString [1 2 []]"), Value::String("1 2 ".to_string())); assert_eq!(eval("toString [1 2 []]"), Value::String("1 2 ".to_string()));
} }
#[test] #[test_log::test]
fn list_with_multiple_empty_lists() { fn list_with_multiple_empty_lists() {
assert_eq!( assert_eq!(
eval("toString [1 [] [] 2]"), eval("toString [1 [] [] 2]"),
@@ -71,7 +71,7 @@ fn list_with_multiple_empty_lists() {
assert_eq!(eval("toString [[] [] 1]"), Value::String("1".to_string())); assert_eq!(eval("toString [[] [] 1]"), Value::String("1".to_string()));
} }
#[test] #[test_log::test]
fn list_with_bool_and_null() { fn list_with_bool_and_null() {
assert_eq!( assert_eq!(
eval("toString [true false null]"), eval("toString [true false null]"),
@@ -83,7 +83,7 @@ fn list_with_bool_and_null() {
); );
} }
#[test] #[test_log::test]
fn mixed_type_list() { fn mixed_type_list() {
assert_eq!( assert_eq!(
eval(r#"toString [1 "hello" 2.5 true]"#), eval(r#"toString [1 "hello" 2.5 true]"#),
@@ -91,7 +91,7 @@ fn mixed_type_list() {
); );
} }
#[test] #[test_log::test]
fn attrs_with_out_path() { fn attrs_with_out_path() {
assert_eq!( assert_eq!(
eval(r#"toString { outPath = "/nix/store/foo"; }"#), eval(r#"toString { outPath = "/nix/store/foo"; }"#),
@@ -99,7 +99,7 @@ fn attrs_with_out_path() {
); );
} }
#[test] #[test_log::test]
fn attrs_with_to_string_method() { fn attrs_with_to_string_method() {
assert_eq!( assert_eq!(
eval(r#"toString { __toString = self: "custom"; }"#), eval(r#"toString { __toString = self: "custom"; }"#),
@@ -107,7 +107,7 @@ fn attrs_with_to_string_method() {
); );
} }
#[test] #[test_log::test]
fn attrs_to_string_self_reference() { fn attrs_to_string_self_reference() {
assert_eq!( assert_eq!(
eval( eval(
@@ -117,7 +117,7 @@ fn attrs_to_string_self_reference() {
); );
} }
#[test] #[test_log::test]
fn attrs_to_string_priority() { fn attrs_to_string_priority() {
assert_eq!( assert_eq!(
eval(r#"toString { __toString = self: "custom"; outPath = "/nix/store/foo"; }"#), eval(r#"toString { __toString = self: "custom"; outPath = "/nix/store/foo"; }"#),
@@ -125,7 +125,7 @@ fn attrs_to_string_priority() {
); );
} }
#[test] #[test_log::test]
fn derivation_like_object() { fn derivation_like_object() {
assert_eq!( assert_eq!(
eval( eval(
@@ -135,7 +135,7 @@ fn derivation_like_object() {
); );
} }
#[test] #[test_log::test]
fn string_interpolation_with_int() { fn string_interpolation_with_int() {
assert_eq!( assert_eq!(
eval(r#""value: ${toString 42}""#), eval(r#""value: ${toString 42}""#),
@@ -143,7 +143,7 @@ fn string_interpolation_with_int() {
); );
} }
#[test] #[test_log::test]
fn string_interpolation_with_list() { fn string_interpolation_with_list() {
assert_eq!( assert_eq!(
eval(r#""items: ${toString [1 2 3]}""#), eval(r#""items: ${toString [1 2 3]}""#),
@@ -151,7 +151,7 @@ fn string_interpolation_with_list() {
); );
} }
#[test] #[test_log::test]
fn nested_to_string_calls() { fn nested_to_string_calls() {
assert_eq!( assert_eq!(
eval(r#"toString (toString 42)"#), eval(r#"toString (toString 42)"#),
@@ -159,7 +159,7 @@ fn nested_to_string_calls() {
); );
} }
#[test] #[test_log::test]
fn to_string_in_let_binding() { fn to_string_in_let_binding() {
assert_eq!( assert_eq!(
eval(r#"let x = toString 42; y = toString 10; in "${x}-${y}""#), eval(r#"let x = toString 42; y = toString 10; in "${x}-${y}""#),
@@ -167,17 +167,17 @@ fn to_string_in_let_binding() {
); );
} }
#[test] #[test_log::test]
fn empty_string() { fn empty_string() {
assert_eq!(eval(r#"toString """#), Value::String("".to_string())); assert_eq!(eval(r#"toString """#), Value::String("".to_string()));
} }
#[test] #[test_log::test]
fn empty_list() { fn empty_list() {
assert_eq!(eval("toString []"), Value::String("".to_string())); assert_eq!(eval("toString []"), Value::String("".to_string()));
} }
#[test] #[test_log::test]
fn to_string_preserves_spaces_in_strings() { fn to_string_preserves_spaces_in_strings() {
assert_eq!( assert_eq!(
eval(r#"toString "hello world""#), eval(r#"toString "hello world""#),
@@ -185,7 +185,7 @@ fn to_string_preserves_spaces_in_strings() {
); );
} }
#[test] #[test_log::test]
fn list_of_empty_strings() { fn list_of_empty_strings() {
assert_eq!( assert_eq!(
eval(r#"toString ["" "" ""]"#), eval(r#"toString ["" "" ""]"#),
@@ -193,7 +193,7 @@ fn list_of_empty_strings() {
); );
} }
#[test] #[test_log::test]
fn deeply_nested_lists() { fn deeply_nested_lists() {
assert_eq!( assert_eq!(
eval("toString [[[1] [2]] [[3] [4]]]"), eval("toString [[[1] [2]] [[3] [4]]]"),
@@ -201,7 +201,7 @@ fn deeply_nested_lists() {
); );
} }
#[test] #[test_log::test]
fn list_with_nested_empty_lists() { fn list_with_nested_empty_lists() {
assert_eq!( assert_eq!(
eval("toString [1 [[]] 2]"), eval("toString [1 [[]] 2]"),
@@ -209,19 +209,19 @@ fn list_with_nested_empty_lists() {
); );
} }
#[test] #[test_log::test]
fn attrs_without_out_path_or_to_string_fails() { fn attrs_without_out_path_or_to_string_fails() {
let result = eval_result(r#"toString { foo = "bar"; }"#); let result = eval_result(r#"toString { foo = "bar"; }"#);
assert!(result.is_err()); assert!(result.is_err());
} }
#[test] #[test_log::test]
fn function_to_string_fails() { fn function_to_string_fails() {
let result = eval_result("toString (x: x)"); let result = eval_result("toString (x: x)");
assert!(result.is_err()); assert!(result.is_err());
} }
#[test] #[test_log::test]
fn to_string_method_must_return_string() { fn to_string_method_must_return_string() {
assert_eq!( assert_eq!(
eval(r#"toString { __toString = self: 42; }"#), eval(r#"toString { __toString = self: 42; }"#),
@@ -233,7 +233,7 @@ fn to_string_method_must_return_string() {
); );
} }
#[test] #[test_log::test]
fn out_path_can_be_nested() { fn out_path_can_be_nested() {
assert_eq!( assert_eq!(
eval(r#"toString { outPath = { outPath = "/final/path"; }; }"#), eval(r#"toString { outPath = { outPath = "/final/path"; }; }"#),
@@ -241,7 +241,7 @@ fn out_path_can_be_nested() {
); );
} }
#[test] #[test_log::test]
fn list_spacing_matches_nix_behavior() { fn list_spacing_matches_nix_behavior() {
assert_eq!( assert_eq!(
eval(r#"toString ["a" "b"]"#), eval(r#"toString ["a" "b"]"#),