refactor(downgrade): use bumpalo
This commit is contained in:
53
Cargo.lock
generated
53
Cargo.lock
generated
@@ -289,9 +289,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.19.1"
|
||||
version = "3.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
|
||||
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
@@ -959,6 +962,27 @@ version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
@@ -2022,6 +2046,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.22.1",
|
||||
"bumpalo",
|
||||
"bzip2",
|
||||
"clap",
|
||||
"criterion",
|
||||
@@ -2061,6 +2086,7 @@ dependencies = [
|
||||
"tap",
|
||||
"tar",
|
||||
"tempfile",
|
||||
"test-log",
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
"toml",
|
||||
@@ -2075,6 +2101,7 @@ name = "nix-js-macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"convert_case 0.11.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
@@ -3393,6 +3420,28 @@ dependencies = [
|
||||
"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]]
|
||||
name = "text-size"
|
||||
version = "1.1.1"
|
||||
|
||||
@@ -8,5 +8,6 @@ proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
convert_case = "0.11"
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0"
|
||||
syn = { version = "2.0", features = ["full"] }
|
||||
|
||||
@@ -4,22 +4,22 @@
|
||||
//! an Intermediate Representation (IR) that follows a specific pattern. It generates:
|
||||
//! 1. An enum representing the different kinds of IR nodes.
|
||||
//! 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.
|
||||
//! 4. `From` implementations to easily convert from a struct variant (e.g., `BinOp`) to the main enum (`Ir::BinOp`).
|
||||
//! 5. A `To[IrName]` trait to provide a convenient `.to_ir()` method on the variant structs.
|
||||
//! 3. `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.
|
||||
|
||||
use convert_case::{Case, Casing};
|
||||
use proc_macro::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{
|
||||
FieldsNamed, Ident, Token, Type, parenthesized,
|
||||
Expr, ExprPath, FieldsNamed, GenericArgument, GenericParam, Generics, Ident, Path, PathSegment,
|
||||
Token, Type, TypePath, parenthesized,
|
||||
parse::{Parse, ParseStream, Result},
|
||||
punctuated::Punctuated,
|
||||
token,
|
||||
};
|
||||
|
||||
/// Represents one of the variants passed to the `ir!` macro.
|
||||
pub enum VariantInput {
|
||||
enum VariantInput {
|
||||
/// A unit-like variant, e.g., `Arg`.
|
||||
Unit(Ident),
|
||||
/// 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.
|
||||
pub struct MacroInput {
|
||||
struct MacroInput {
|
||||
/// 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.
|
||||
pub variants: Punctuated<VariantInput, Token![,]>,
|
||||
variants: Punctuated<VariantInput, Token![,]>,
|
||||
}
|
||||
|
||||
impl Parse for VariantInput {
|
||||
@@ -64,13 +65,14 @@ impl Parse for VariantInput {
|
||||
|
||||
impl Parse for MacroInput {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
// The macro input is expected to be: `IrName, Variant1, Variant2, ...`
|
||||
let base_name = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
let generics = Generics::parse(input)?;
|
||||
input.parse::<Token![;]>()?;
|
||||
let variants = Punctuated::parse_terminated(input)?;
|
||||
|
||||
Ok(MacroInput {
|
||||
base_name,
|
||||
generics,
|
||||
variants,
|
||||
})
|
||||
}
|
||||
@@ -81,17 +83,39 @@ pub fn ir_impl(input: TokenStream) -> TokenStream {
|
||||
let parsed_input = syn::parse_macro_input!(input as MacroInput);
|
||||
|
||||
let base_name = &parsed_input.base_name;
|
||||
let ref_name = format_ident!("{}Ref", base_name);
|
||||
let mut_name = format_ident!("{}Mut", base_name);
|
||||
let generic_params = &parsed_input.generics.params;
|
||||
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_fn_name = format_ident!("to_{}", base_name.to_string().to_case(Case::Snake));
|
||||
|
||||
let mut enum_variants = 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 from_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) });
|
||||
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 });
|
||||
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) }
|
||||
}
|
||||
});
|
||||
to_trait_impls.push(quote! {
|
||||
impl #to_trait_name for #name {
|
||||
fn #to_trait_fn_name(self) -> #base_name { #base_name::from(self) }
|
||||
impl <#generic_params> #to_trait_name <#generic_args> for #name #where_clause {
|
||||
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();
|
||||
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 });
|
||||
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) }
|
||||
}
|
||||
});
|
||||
to_trait_impls.push(quote! {
|
||||
impl #to_trait_name for #name {
|
||||
fn #to_trait_fn_name(self) -> #base_name { #base_name::from(self) }
|
||||
impl <#generic_params> #to_trait_name <#generic_args> for #name #where_clause {
|
||||
fn #to_trait_fn_name(self) -> #base_name <#generic_args> { #base_name::from(self) }
|
||||
}
|
||||
});
|
||||
}
|
||||
VariantInput::Struct(name, mut fields) => {
|
||||
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 {
|
||||
attrs: vec![],
|
||||
vis: syn::Visibility::Public(syn::token::Pub::default()),
|
||||
@@ -168,22 +187,18 @@ pub fn ir_impl(input: TokenStream) -> TokenStream {
|
||||
|
||||
struct_defs.push(quote! {
|
||||
#[derive(Debug)]
|
||||
pub struct #name #fields
|
||||
pub struct #name <#generic_params> #where_clause #fields
|
||||
});
|
||||
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) });
|
||||
enum_variants.push(quote! { #name(#inner_type <#generic_args>) });
|
||||
span_arms.push(quote! { Self::#name(inner) => inner.span });
|
||||
from_impls.push(quote! {
|
||||
impl From<#inner_type> for #base_name {
|
||||
fn from(val: #inner_type) -> Self { #base_name::#name(val) }
|
||||
impl <#generic_params> From<#inner_type <#generic_args>> for #base_name <#generic_args> #where_clause {
|
||||
fn from(val: #inner_type <#generic_args>) -> Self { #base_name::#name(val) }
|
||||
}
|
||||
});
|
||||
to_trait_impls.push(quote! {
|
||||
impl #to_trait_name for #name {
|
||||
fn #to_trait_fn_name(self) -> #base_name { #base_name::from(self) }
|
||||
impl <#generic_params> #to_trait_name <#generic_args> for #name <#generic_args> #where_clause {
|
||||
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.
|
||||
let expanded = quote! {
|
||||
/// The main IR enum, generated by the `ir!` macro.
|
||||
#[derive(Debug, IsVariant, Unwrap, TryUnwrap)]
|
||||
pub enum #base_name {
|
||||
#[derive(Debug)]
|
||||
pub enum #base_name <#generic_params> #where_clause {
|
||||
#( #enum_variants ),*
|
||||
}
|
||||
|
||||
// The struct definitions for the enum variants.
|
||||
#( #struct_defs )*
|
||||
|
||||
/// An immutable reference version of the IR enum.
|
||||
#[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 ),*
|
||||
}
|
||||
}
|
||||
|
||||
impl <#generic_params> #base_name <#generic_args> #where_clause {
|
||||
pub fn span(&self) -> rnix::TextRange {
|
||||
match self {
|
||||
#( #span_arms ),*
|
||||
@@ -239,9 +228,9 @@ pub fn ir_impl(input: TokenStream) -> TokenStream {
|
||||
#( #from_impls )*
|
||||
|
||||
/// 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.
|
||||
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.
|
||||
|
||||
@@ -27,6 +27,7 @@ miette = { version = "7.4", features = ["fancy"] }
|
||||
|
||||
hashbrown = "0.16"
|
||||
string-interner = "0.19"
|
||||
bumpalo = { version = "3.20", features = ["allocator-api2", "boxed", "collections"] }
|
||||
|
||||
rust-embed="8.11"
|
||||
|
||||
@@ -80,6 +81,7 @@ prof = []
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "0.8", features = ["html_reports"] }
|
||||
test-log = { version = "0.2", features = ["trace"] }
|
||||
|
||||
[[bench]]
|
||||
name = "basic_ops"
|
||||
|
||||
164
nix-js/runtime-ts/package-lock.json
generated
164
nix-js/runtime-ts/package-lock.json
generated
@@ -8,16 +8,15 @@
|
||||
"name": "nix-js-runtime",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@eslint/json": "^1.0.1",
|
||||
"eslint": "^9.39.2",
|
||||
"globals": "^17.3.0",
|
||||
"jiti": "^2.6.1",
|
||||
"js-sdsl": "^4.4.2",
|
||||
"typescript-eslint": "^8.55.0"
|
||||
"js-sdsl": "^4.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"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": {
|
||||
@@ -449,6 +448,7 @@
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
|
||||
"integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eslint-visitor-keys": "^3.4.3"
|
||||
@@ -467,6 +467,7 @@
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
|
||||
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
@@ -479,6 +480,7 @@
|
||||
"version": "4.12.2",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
|
||||
"integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
|
||||
@@ -488,6 +490,7 @@
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/config-array/-/config-array-0.21.1.tgz",
|
||||
"integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@eslint/object-schema": "^2.1.7",
|
||||
@@ -502,6 +505,7 @@
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
|
||||
"integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@eslint/core": "^0.17.0"
|
||||
@@ -514,6 +518,7 @@
|
||||
"version": "0.17.0",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/core/-/core-0.17.0.tgz",
|
||||
"integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.15"
|
||||
@@ -522,22 +527,11 @@
|
||||
"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": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
|
||||
"integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.4",
|
||||
@@ -561,6 +555,7 @@
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/globals/-/globals-14.0.0.tgz",
|
||||
"integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -573,6 +568,7 @@
|
||||
"version": "9.39.2",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/js/-/js-9.39.2.tgz",
|
||||
"integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -581,47 +577,21 @@
|
||||
"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": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/object-schema/-/object-schema-2.1.7.tgz",
|
||||
"integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"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": {
|
||||
"version": "0.19.1",
|
||||
"resolved": "https://registry.npmmirror.com/@humanfs/core/-/core-0.19.1.tgz",
|
||||
"integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=18.18.0"
|
||||
@@ -631,6 +601,7 @@
|
||||
"version": "0.16.7",
|
||||
"resolved": "https://registry.npmmirror.com/@humanfs/node/-/node-0.16.7.tgz",
|
||||
"integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@humanfs/core": "^0.19.1",
|
||||
@@ -644,6 +615,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
|
||||
"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=12.22"
|
||||
@@ -653,19 +625,11 @@
|
||||
"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": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmmirror.com/@humanwhocodes/retry/-/retry-0.4.3.tgz",
|
||||
"integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=18.18"
|
||||
@@ -679,18 +643,21 @@
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz",
|
||||
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.55.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.55.0.tgz",
|
||||
"integrity": "sha512-1y/MVSz0NglV1ijHC8OT49mPJ4qhPYjiK08YUQVbIOyu+5k862LKUHFkpKHWu//zmr7hDR2rhwUm6gnCGNmGBQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.12.2",
|
||||
@@ -719,6 +686,7 @@
|
||||
"version": "7.0.5",
|
||||
"resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz",
|
||||
"integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
@@ -728,6 +696,7 @@
|
||||
"version": "8.55.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.55.0.tgz",
|
||||
"integrity": "sha512-4z2nCSBfVIMnbuu8uinj+f0o4qOeggYJLbjpPHka3KH1om7e+H9yLKTYgksTaHcGco+NClhhY2vyO3HsMH1RGw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
@@ -753,6 +722,7 @@
|
||||
"version": "8.55.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.55.0.tgz",
|
||||
"integrity": "sha512-zRcVVPFUYWa3kNnjaZGXSu3xkKV1zXy8M4nO/pElzQhFweb7PPtluDLQtKArEOGmjXoRjnUZ29NjOiF0eCDkcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/tsconfig-utils": "^8.55.0",
|
||||
@@ -774,6 +744,7 @@
|
||||
"version": "8.55.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.55.0.tgz",
|
||||
"integrity": "sha512-fVu5Omrd3jeqeQLiB9f1YsuK/iHFOwb04bCtY4BSCLgjNbOD33ZdV6KyEqplHr+IlpgT0QTZ/iJ+wT7hvTx49Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.55.0",
|
||||
@@ -791,6 +762,7 @@
|
||||
"version": "8.55.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.55.0.tgz",
|
||||
"integrity": "sha512-1R9cXqY7RQd7WuqSN47PK9EDpgFUK3VqdmbYrvWJZYDd0cavROGn+74ktWBlmJ13NXUQKlZ/iAEQHI/V0kKe0Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -807,6 +779,7 @@
|
||||
"version": "8.55.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.55.0.tgz",
|
||||
"integrity": "sha512-x1iH2unH4qAt6I37I2CGlsNs+B9WGxurP2uyZLRz6UJoZWDBx9cJL1xVN/FiOmHEONEg6RIufdvyT0TEYIgC5g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.55.0",
|
||||
@@ -831,6 +804,7 @@
|
||||
"version": "8.55.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.55.0.tgz",
|
||||
"integrity": "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -844,6 +818,7 @@
|
||||
"version": "8.55.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.55.0.tgz",
|
||||
"integrity": "sha512-EwrH67bSWdx/3aRQhCoxDaHM+CrZjotc2UCCpEDVqfCE+7OjKAGWNY2HsCSTEVvWH2clYQK8pdeLp42EVs+xQw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/project-service": "8.55.0",
|
||||
@@ -871,6 +846,7 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
@@ -880,6 +856,7 @@
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz",
|
||||
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
@@ -895,6 +872,7 @@
|
||||
"version": "8.55.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.55.0.tgz",
|
||||
"integrity": "sha512-BqZEsnPGdYpgyEIkDC1BadNY8oMwckftxBT+C8W0g1iKPdeqKZBtTfnvcq0nf60u7MkjFO8RBvpRGZBPw4L2ow==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.9.1",
|
||||
@@ -918,6 +896,7 @@
|
||||
"version": "8.55.0",
|
||||
"resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.55.0.tgz",
|
||||
"integrity": "sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.55.0",
|
||||
@@ -935,6 +914,7 @@
|
||||
"version": "8.15.0",
|
||||
"resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
@@ -948,6 +928,7 @@
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
|
||||
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
@@ -957,6 +938,7 @@
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
@@ -973,6 +955,7 @@
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
@@ -988,18 +971,21 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true,
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
@@ -1010,6 +996,7 @@
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz",
|
||||
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
@@ -1019,6 +1006,7 @@
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
@@ -1035,6 +1023,7 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
@@ -1047,18 +1036,21 @@
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
@@ -1073,6 +1065,7 @@
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz",
|
||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
@@ -1090,6 +1083,7 @@
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz",
|
||||
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
@@ -1137,6 +1131,7 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
@@ -1149,6 +1144,7 @@
|
||||
"version": "9.39.2",
|
||||
"resolved": "https://registry.npmmirror.com/eslint/-/eslint-9.39.2.tgz",
|
||||
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
@@ -1209,6 +1205,7 @@
|
||||
"version": "8.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-8.4.0.tgz",
|
||||
"integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"esrecurse": "^4.3.0",
|
||||
@@ -1225,6 +1222,7 @@
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
|
||||
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -1237,6 +1235,7 @@
|
||||
"version": "0.17.0",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/core/-/core-0.17.0.tgz",
|
||||
"integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.15"
|
||||
@@ -1249,6 +1248,7 @@
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
|
||||
"integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@eslint/core": "^0.17.0",
|
||||
@@ -1262,6 +1262,7 @@
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/espree/-/espree-10.4.0.tgz",
|
||||
"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"acorn": "^8.15.0",
|
||||
@@ -1279,6 +1280,7 @@
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.7.0.tgz",
|
||||
"integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"estraverse": "^5.1.0"
|
||||
@@ -1291,6 +1293,7 @@
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz",
|
||||
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"estraverse": "^5.2.0"
|
||||
@@ -1303,6 +1306,7 @@
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz",
|
||||
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
@@ -1312,6 +1316,7 @@
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz",
|
||||
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
@@ -1321,24 +1326,28 @@
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-levenshtein": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fdir": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz",
|
||||
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
@@ -1356,6 +1365,7 @@
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
|
||||
"integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"flat-cache": "^4.0.0"
|
||||
@@ -1368,6 +1378,7 @@
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz",
|
||||
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"locate-path": "^6.0.0",
|
||||
@@ -1384,6 +1395,7 @@
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-4.0.1.tgz",
|
||||
"integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"flatted": "^3.2.9",
|
||||
@@ -1397,12 +1409,14 @@
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.3.3.tgz",
|
||||
"integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/glob-parent": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz",
|
||||
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.3"
|
||||
@@ -1427,6 +1441,7 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -1436,6 +1451,7 @@
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz",
|
||||
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
@@ -1445,6 +1461,7 @@
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.1.tgz",
|
||||
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"parent-module": "^1.0.0",
|
||||
@@ -1461,6 +1478,7 @@
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.8.19"
|
||||
@@ -1470,6 +1488,7 @@
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
@@ -1479,6 +1498,7 @@
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
@@ -1491,6 +1511,7 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/jiti": {
|
||||
@@ -1517,6 +1538,7 @@
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
@@ -1529,24 +1551,28 @@
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz",
|
||||
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-stable-stringify-without-jsonify": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
|
||||
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/keyv": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
|
||||
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"json-buffer": "3.0.1"
|
||||
@@ -1556,6 +1582,7 @@
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz",
|
||||
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prelude-ls": "^1.2.1",
|
||||
@@ -1569,6 +1596,7 @@
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz",
|
||||
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"p-locate": "^5.0.0"
|
||||
@@ -1584,12 +1612,14 @@
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
@@ -1602,18 +1632,21 @@
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/natural-compare": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz",
|
||||
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/optionator": {
|
||||
"version": "0.9.4",
|
||||
"resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz",
|
||||
"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"deep-is": "^0.1.3",
|
||||
@@ -1631,6 +1664,7 @@
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz",
|
||||
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"yocto-queue": "^0.1.0"
|
||||
@@ -1646,6 +1680,7 @@
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz",
|
||||
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"p-limit": "^3.0.2"
|
||||
@@ -1661,6 +1696,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz",
|
||||
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"callsites": "^3.0.0"
|
||||
@@ -1673,6 +1709,7 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -1682,6 +1719,7 @@
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -1691,6 +1729,7 @@
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz",
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
@@ -1704,6 +1743,7 @@
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
@@ -1713,6 +1753,7 @@
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
@@ -1722,6 +1763,7 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
@@ -1731,6 +1773,7 @@
|
||||
"version": "7.7.4",
|
||||
"resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.4.tgz",
|
||||
"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
@@ -1743,6 +1786,7 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
@@ -1755,6 +1799,7 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -1764,6 +1809,7 @@
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
||||
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -1776,6 +1822,7 @@
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
@@ -1788,6 +1835,7 @@
|
||||
"version": "0.2.15",
|
||||
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fdir": "^6.5.0",
|
||||
@@ -1804,6 +1852,7 @@
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-2.4.0.tgz",
|
||||
"integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.12"
|
||||
@@ -1816,6 +1865,7 @@
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz",
|
||||
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prelude-ls": "^1.2.1"
|
||||
@@ -1828,6 +1878,7 @@
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
@@ -1842,6 +1893,7 @@
|
||||
"version": "8.55.0",
|
||||
"resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.55.0.tgz",
|
||||
"integrity": "sha512-HE4wj+r5lmDVS9gdaN0/+iqNvPZwGfnJ5lZuz7s5vLlg9ODw0bIiiETaios9LvFI1U94/VBXGm3CB2Y5cNFMpw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "8.55.0",
|
||||
@@ -1865,6 +1917,7 @@
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"punycode": "^2.1.0"
|
||||
@@ -1874,6 +1927,7 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
@@ -1889,6 +1943,7 @@
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz",
|
||||
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
@@ -1898,6 +1953,7 @@
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
|
||||
@@ -10,12 +10,13 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"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": {
|
||||
"eslint": "^9.39.2",
|
||||
"globals": "^17.3.0",
|
||||
"js-sdsl": "^4.4.2",
|
||||
"typescript-eslint": "^8.55.0"
|
||||
"js-sdsl": "^4.4.2"
|
||||
}
|
||||
}
|
||||
|
||||
1
nix-js/runtime-ts/src/types/global.d.ts
vendored
1
nix-js/runtime-ts/src/types/global.d.ts
vendored
@@ -1,6 +1,5 @@
|
||||
import type { NixRuntime } from "..";
|
||||
import type { builtins } from "../builtins";
|
||||
import { JsonValue } from "../builtins/conversion";
|
||||
import type { FetchGitResult, FetchTarballResult, FetchUrlResult } from "../builtins/io";
|
||||
import type {
|
||||
assert,
|
||||
|
||||
@@ -188,7 +188,6 @@ impl<Ctx: CodegenContext> Compile<Ctx> for rnix::TextRange {
|
||||
}
|
||||
|
||||
pub(crate) trait CodegenContext {
|
||||
fn get_ir(&self, id: ExprId) -> &Ir;
|
||||
fn get_sym(&self, id: SymId) -> Symbol<'_>;
|
||||
fn get_current_dir(&self) -> &Path;
|
||||
fn get_store_dir(&self) -> &str;
|
||||
@@ -196,19 +195,13 @@ pub(crate) trait CodegenContext {
|
||||
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<'_> {
|
||||
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
|
||||
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) {
|
||||
match self {
|
||||
Ir::Int(int) => {
|
||||
@@ -224,11 +217,11 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Ir {
|
||||
code!(buf, ctx; "null");
|
||||
}
|
||||
Ir::Str(s) => {
|
||||
code!(buf, ctx; quoted(&s.val));
|
||||
code!(buf, ctx; quoted(&s.inner));
|
||||
}
|
||||
Ir::Path(p) => {
|
||||
// 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::BinOp(x) => x.compile(ctx, buf),
|
||||
@@ -265,14 +258,12 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Ir {
|
||||
ref assertion_raw,
|
||||
span: assert_span,
|
||||
}) => {
|
||||
let assertion = ctx.get_ir(assertion);
|
||||
|
||||
// Nix.assert
|
||||
code!(buf, ctx;
|
||||
"$a("
|
||||
assertion
|
||||
","
|
||||
ctx.get_ir(expr)
|
||||
expr
|
||||
","
|
||||
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) {
|
||||
let &If {
|
||||
cond,
|
||||
@@ -324,19 +315,18 @@ impl<Ctx: CodegenContext> Compile<Ctx> for If {
|
||||
alter,
|
||||
span: _,
|
||||
} = self;
|
||||
let cond = ctx.get_ir(cond);
|
||||
|
||||
// Nix.forceBool
|
||||
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) {
|
||||
use BinOpKind::*;
|
||||
|
||||
let lhs = ctx.get_ir(self.lhs);
|
||||
let rhs = ctx.get_ir(self.rhs);
|
||||
let lhs = self.lhs;
|
||||
let rhs = self.rhs;
|
||||
|
||||
match self.kind {
|
||||
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) {
|
||||
use UnOpKind::*;
|
||||
let rhs = ctx.get_ir(self.rhs);
|
||||
let rhs = self.rhs;
|
||||
match self.kind {
|
||||
Neg => {
|
||||
code!(buf, ctx; "$os(0n," rhs ")");
|
||||
}
|
||||
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) {
|
||||
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();
|
||||
|
||||
@@ -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) {
|
||||
code!(buf, ctx;
|
||||
"$c("
|
||||
ctx.get_ir(self.func)
|
||||
self.func
|
||||
","
|
||||
ctx.get_ir(self.arg)
|
||||
self.arg
|
||||
","
|
||||
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) {
|
||||
if self.is_empty() {
|
||||
return;
|
||||
@@ -474,28 +470,27 @@ impl<Ctx: CodegenContext> Compile<Ctx> for [(ExprId, ExprId)] {
|
||||
buf, ctx;
|
||||
"const "
|
||||
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) {
|
||||
if self.thunks.is_empty() {
|
||||
ctx.get_ir(self.body).compile(ctx, buf);
|
||||
self.body.compile(ctx, buf);
|
||||
} else {
|
||||
let body = ctx.get_ir(self.body);
|
||||
code!(buf, ctx; "(()=>{" self.thunks "return " body "})()");
|
||||
code!(buf, ctx; "(()=>{" self.thunks "return " self.body "})()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ctx: CodegenContext> Compile<Ctx> for WithExpr {
|
||||
impl<Ctx: CodegenContext> Compile<Ctx> for WithExpr<'_> {
|
||||
fn compile(&self, ctx: &Ctx, buf: &mut CodeBuffer) {
|
||||
let namespace = ctx.get_ir(self.namespace);
|
||||
let body = ctx.get_ir(self.body);
|
||||
let namespace = self.namespace;
|
||||
let body = self.body;
|
||||
let has_thunks = !self.thunks.is_empty();
|
||||
if has_thunks {
|
||||
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) {
|
||||
if let Some(default) = self.default {
|
||||
code!(buf, ctx;
|
||||
"$sd("
|
||||
ctx.get_ir(self.expr)
|
||||
self.expr
|
||||
",["
|
||||
joined(self.attrpath.iter(), ",", |ctx: &Ctx, buf, attr| {
|
||||
match attr {
|
||||
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
|
||||
")"
|
||||
@@ -527,12 +522,12 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Select {
|
||||
} else {
|
||||
code!(buf, ctx;
|
||||
"$s("
|
||||
ctx.get_ir(self.expr)
|
||||
self.expr
|
||||
",["
|
||||
joined(self.attrpath.iter(), ",", |ctx: &Ctx, buf, attr| {
|
||||
match attr {
|
||||
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) {
|
||||
if !self.dyns.is_empty() {
|
||||
code!(buf, ctx;
|
||||
"$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 val = ctx.get_ir(expr);
|
||||
|
||||
code!(
|
||||
buf, ctx;
|
||||
"[" key "," val "]"
|
||||
@@ -563,11 +556,10 @@ impl<Ctx: CodegenContext> Compile<Ctx> for AttrSet {
|
||||
})
|
||||
"]),{dynKeys:["
|
||||
joined(self.dyns.iter(), ",", |ctx: &Ctx, buf, (key, _, _)| {
|
||||
code!(buf, ctx; ctx.get_ir(*key));
|
||||
code!(buf, ctx; key);
|
||||
})
|
||||
"],dynVals:["
|
||||
joined(self.dyns.iter(), ",", |ctx: &Ctx, buf, (_, val, _)| {
|
||||
let val = ctx.get_ir(*val);
|
||||
code!(buf, ctx; val);
|
||||
})
|
||||
"],dynSpans:["
|
||||
@@ -579,10 +571,8 @@ impl<Ctx: CodegenContext> Compile<Ctx> for AttrSet {
|
||||
} else if !self.stcs.is_empty() {
|
||||
code!(buf, ctx;
|
||||
"$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 val = ctx.get_ir(expr);
|
||||
|
||||
code!(
|
||||
buf, ctx;
|
||||
"[" 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) {
|
||||
code!(buf, ctx;
|
||||
"["
|
||||
joined(self.items.iter(), ",", |ctx: &Ctx, buf, item| {
|
||||
let item = ctx.get_ir(*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) {
|
||||
code!(buf, ctx;
|
||||
"$cs(["
|
||||
joined(self.parts.iter(), ",", |ctx: &Ctx, buf, part| {
|
||||
let part = ctx.get_ir(*part);
|
||||
code!(buf, ctx; part);
|
||||
})
|
||||
"]," 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) {
|
||||
code!(buf, ctx;
|
||||
"$h("
|
||||
ctx.get_ir(self.lhs)
|
||||
self.lhs
|
||||
",["
|
||||
joined(self.rhs.iter(), ",", |ctx: &Ctx, buf, attr| {
|
||||
match attr {
|
||||
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),
|
||||
}
|
||||
})
|
||||
"])"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::cell::UnsafeCell;
|
||||
use std::path::Path;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use bumpalo::Bump;
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use rnix::TextRange;
|
||||
use string_interner::DefaultStringInterner;
|
||||
@@ -10,8 +10,8 @@ use crate::codegen::{CodegenContext, compile, compile_scoped};
|
||||
use crate::downgrade::*;
|
||||
use crate::error::{Error, Result, Source};
|
||||
use crate::ir::{
|
||||
Arg, ArgId, Bool, Builtin, ExprId, Ir, Null, ReplBinding, ScopedImportBinding, SymId, Thunk,
|
||||
ToIr as _, WithLookup,
|
||||
Arg, ArgId, Bool, Builtin, Ir, IrRef, Null, ReplBinding, ScopedImportBinding, SymId, Thunk,
|
||||
ThunkId, ToIr as _, WithLookup,
|
||||
};
|
||||
#[cfg(feature = "inspector")]
|
||||
use crate::runtime::inspector::InspectorServer;
|
||||
@@ -183,12 +183,23 @@ impl Context {
|
||||
}
|
||||
|
||||
pub(crate) struct Ctx {
|
||||
irs: Vec<Ir>,
|
||||
symbols: DefaultStringInterner,
|
||||
global: NonNull<HashMap<SymId, ExprId>>,
|
||||
global: HashMap<SymId, Ir<'static>>,
|
||||
sources: Vec<Source>,
|
||||
store: DaemonStore,
|
||||
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 {
|
||||
@@ -196,19 +207,15 @@ impl Ctx {
|
||||
use crate::ir::{Builtins, ToIr as _};
|
||||
|
||||
let mut symbols = DefaultStringInterner::new();
|
||||
let mut irs = Vec::new();
|
||||
let mut global = HashMap::new();
|
||||
|
||||
irs.push(
|
||||
let builtins_sym = symbols.get_or_intern("builtins");
|
||||
global.insert(
|
||||
builtins_sym,
|
||||
Builtins {
|
||||
span: rnix::TextRange::default(),
|
||||
span: TextRange::default(),
|
||||
}
|
||||
.to_ir(),
|
||||
);
|
||||
let builtins_expr = ExprId(0);
|
||||
|
||||
let builtins_sym = symbols.get_or_intern("builtins");
|
||||
global.insert(builtins_sym, builtins_expr);
|
||||
|
||||
let free_globals = [
|
||||
"abort",
|
||||
@@ -258,22 +265,17 @@ impl Ctx {
|
||||
];
|
||||
|
||||
for name in free_globals {
|
||||
let name_sym = symbols.get_or_intern(name);
|
||||
let id = ExprId(irs.len());
|
||||
irs.push(
|
||||
Builtin {
|
||||
inner: name_sym,
|
||||
let name = symbols.get_or_intern(name);
|
||||
let value = Builtin {
|
||||
inner: name,
|
||||
span: rnix::TextRange::default(),
|
||||
}
|
||||
.to_ir(),
|
||||
);
|
||||
global.insert(name_sym, id);
|
||||
.to_ir();
|
||||
global.insert(name, value);
|
||||
}
|
||||
for (name, value) in consts {
|
||||
let name_sym = symbols.get_or_intern(name);
|
||||
let id = ExprId(irs.len());
|
||||
irs.push(value);
|
||||
global.insert(name_sym, id);
|
||||
let name = symbols.get_or_intern(name);
|
||||
global.insert(name, value);
|
||||
}
|
||||
|
||||
let config = StoreConfig::from_env();
|
||||
@@ -281,17 +283,28 @@ impl Ctx {
|
||||
|
||||
Ok(Self {
|
||||
symbols,
|
||||
irs,
|
||||
global: unsafe { NonNull::new_unchecked(Box::leak(Box::new(global))) },
|
||||
global,
|
||||
sources: Vec::new(),
|
||||
store,
|
||||
spans: UnsafeCell::new(Vec::new()),
|
||||
thunk_count: 0,
|
||||
})
|
||||
}
|
||||
|
||||
fn downgrade_ctx<'a>(&'a mut self, extra_scope: Option<Scope<'a>>) -> DowngradeCtx<'a> {
|
||||
let global_ref = unsafe { self.global.as_ref() };
|
||||
DowngradeCtx::new(self, global_ref, extra_scope)
|
||||
fn downgrade_ctx<'ctx, 'ir>(
|
||||
&'ctx mut self,
|
||||
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 {
|
||||
@@ -313,7 +326,11 @@ impl Ctx {
|
||||
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");
|
||||
|
||||
self.sources.push(source.clone());
|
||||
@@ -326,13 +343,22 @@ impl Ctx {
|
||||
.tree()
|
||||
.expr()
|
||||
.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)?;
|
||||
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);
|
||||
Ok(code)
|
||||
}
|
||||
@@ -346,16 +372,13 @@ impl Ctx {
|
||||
);
|
||||
let root = self.downgrade(source, Some(scope))?;
|
||||
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);
|
||||
Ok(code)
|
||||
}
|
||||
}
|
||||
|
||||
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<'_> {
|
||||
self.symbols
|
||||
.resolve(id)
|
||||
@@ -401,95 +424,50 @@ impl RuntimeContext for Ctx {
|
||||
fn get_store(&self) -> &DaemonStore {
|
||||
&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() };
|
||||
spans[id]
|
||||
}
|
||||
}
|
||||
|
||||
enum Scope<'ctx> {
|
||||
Global(&'ctx HashMap<SymId, ExprId>),
|
||||
enum Scope<'ctx, 'ir> {
|
||||
Global(&'ctx HashMap<SymId, Ir<'static>>),
|
||||
Repl(&'ctx HashSet<SymId>),
|
||||
ScopedImport(HashSet<SymId>),
|
||||
Let(HashMap<SymId, ExprId>),
|
||||
Param(SymId, ExprId),
|
||||
Let(HashMap<SymId, ThunkId>),
|
||||
Param(SymId, IrRef<'ir>),
|
||||
}
|
||||
|
||||
struct ScopeGuard<'a, 'ctx> {
|
||||
ctx: &'a mut DowngradeCtx<'ctx>,
|
||||
struct ScopeGuard<'a, 'ctx, 'ir> {
|
||||
ctx: &'a mut DowngradeCtx<'ctx, 'ir>,
|
||||
}
|
||||
|
||||
impl<'a, 'ctx> Drop for ScopeGuard<'a, 'ctx> {
|
||||
impl Drop for ScopeGuard<'_, '_, '_> {
|
||||
fn drop(&mut self) {
|
||||
self.ctx.scopes.pop();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'ctx> ScopeGuard<'a, 'ctx> {
|
||||
fn as_ctx(&mut self) -> &mut DowngradeCtx<'ctx> {
|
||||
impl<'ir, 'ctx> ScopeGuard<'_, 'ctx, 'ir> {
|
||||
fn as_ctx(&mut self) -> &mut DowngradeCtx<'ctx, 'ir> {
|
||||
self.ctx
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DowngradeCtx<'ctx> {
|
||||
ctx: &'ctx mut Ctx,
|
||||
irs: Vec<Ir>,
|
||||
scopes: Vec<Scope<'ctx>>,
|
||||
pub struct DowngradeCtx<'ctx, 'ir> {
|
||||
bump: &'ir Bump,
|
||||
symbols: &'ctx mut DefaultStringInterner,
|
||||
source: Source,
|
||||
scopes: Vec<Scope<'ctx, 'ir>>,
|
||||
with_scope_count: usize,
|
||||
arg_id: usize,
|
||||
thunk_scopes: Vec<Vec<(ExprId, ExprId)>>,
|
||||
arg_count: usize,
|
||||
thunk_count: &'ctx mut usize,
|
||||
thunk_scopes: Vec<bumpalo::collections::Vec<'ir, (ThunkId, IrRef<'ir>)>>,
|
||||
}
|
||||
|
||||
impl<'ctx> DowngradeCtx<'ctx> {
|
||||
fn new(
|
||||
ctx: &'ctx mut Ctx,
|
||||
global: &'ctx HashMap<SymId, ExprId>,
|
||||
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 {
|
||||
fn should_thunk(ir: IrRef<'_>) -> bool {
|
||||
!matches!(
|
||||
ir,
|
||||
Ir::Builtin(_)
|
||||
| Ir::Builtins(_)
|
||||
| Ir::Int(_)
|
||||
@@ -497,30 +475,78 @@ impl DowngradeContext for DowngradeCtx<'_> {
|
||||
| Ir::Bool(_)
|
||||
| Ir::Null(_)
|
||||
| Ir::Str(_)
|
||||
| Ir::Thunk(_) => id,
|
||||
_ => {
|
||||
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());
|
||||
self.register_thunk(slot, id);
|
||||
slot
|
||||
| Ir::Thunk(_)
|
||||
)
|
||||
}
|
||||
|
||||
impl<'ctx, 'ir> DowngradeCtx<'ctx, 'ir> {
|
||||
fn new(
|
||||
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 {
|
||||
self.ctx.symbols.get_or_intern(sym)
|
||||
self.symbols.get_or_intern(sym)
|
||||
}
|
||||
|
||||
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() {
|
||||
match scope {
|
||||
&Scope::Global(global_scope) => {
|
||||
if let Some(&expr) = global_scope.get(&sym) {
|
||||
if let Some(expr) = global_scope.get(&sym) {
|
||||
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 {
|
||||
self.ctx.get_current_source()
|
||||
self.source.clone()
|
||||
}
|
||||
|
||||
#[allow(refining_impl_trait)]
|
||||
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
|
||||
fn with_let_scope<F, R>(&mut self, keys: &[SymId], f: F) -> Result<R>
|
||||
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;
|
||||
*self.thunk_count += keys.len();
|
||||
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())
|
||||
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
|
||||
F: FnOnce(&mut Self) -> R,
|
||||
{
|
||||
@@ -619,11 +628,15 @@ impl DowngradeContext for DowngradeCtx<'_> {
|
||||
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
|
||||
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);
|
||||
(
|
||||
ret,
|
||||
@@ -631,10 +644,17 @@ impl DowngradeContext for DowngradeCtx<'_> {
|
||||
)
|
||||
}
|
||||
|
||||
fn register_thunk(&mut self, slot: ExprId, inner: ExprId) {
|
||||
self.thunk_scopes
|
||||
.last_mut()
|
||||
.expect("register_thunk without active scope")
|
||||
.push((slot, inner));
|
||||
fn bump(&self) -> &'ir bumpalo::Bump {
|
||||
self.bump
|
||||
}
|
||||
}
|
||||
|
||||
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
@@ -1,46 +1,48 @@
|
||||
use derive_more::{IsVariant, TryUnwrap, Unwrap};
|
||||
use hashbrown::HashMap;
|
||||
use bumpalo::{Bump, boxed::Box, collections::Vec};
|
||||
use rnix::{TextRange, ast};
|
||||
use string_interner::symbol::SymbolU32;
|
||||
|
||||
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>;
|
||||
|
||||
Int(i64),
|
||||
Float(f64),
|
||||
Bool(bool),
|
||||
Null,
|
||||
Str { pub val: String },
|
||||
AttrSet { pub stcs: HashMap<SymId, (ExprId, rnix::TextRange)>, pub dyns: Vec<(ExprId, ExprId, rnix::TextRange)> },
|
||||
List { pub items: Vec<ExprId> },
|
||||
Str { inner: Box<'ir, String> },
|
||||
AttrSet { stcs: HashMap<'ir, SymId, (IrRef<'ir>, TextRange)>, dyns: Vec<'ir, (IrRef<'ir>, IrRef<'ir>, TextRange)> },
|
||||
List { items: Vec<'ir, IrRef<'ir>> },
|
||||
|
||||
HasAttr { pub lhs: ExprId, pub rhs: Vec<Attr> },
|
||||
BinOp { pub lhs: ExprId, pub rhs: ExprId, pub kind: BinOpKind },
|
||||
UnOp { pub rhs: ExprId, pub kind: UnOpKind },
|
||||
Select { pub expr: ExprId, pub attrpath: Vec<Attr>, pub default: Option<ExprId> },
|
||||
If { pub cond: ExprId, pub consq: ExprId, pub alter: ExprId },
|
||||
Call { pub func: ExprId, pub arg: ExprId },
|
||||
Assert { pub assertion: ExprId, pub expr: ExprId, pub assertion_raw: String },
|
||||
ConcatStrings { pub parts: Vec<ExprId>, pub force_string: bool },
|
||||
Path { pub expr: ExprId },
|
||||
Func { pub body: ExprId, pub param: Option<Param>, pub arg: ExprId, pub thunks: Vec<(ExprId, ExprId)> },
|
||||
TopLevel { pub body: ExprId, pub thunks: Vec<(ExprId, ExprId)> },
|
||||
HasAttr { lhs: IrRef<'ir>, rhs: Vec<'ir, Attr<'ir>> },
|
||||
BinOp { lhs: IrRef<'ir>, rhs: IrRef<'ir>, kind: BinOpKind },
|
||||
UnOp { rhs: IrRef<'ir>, kind: UnOpKind },
|
||||
Select { expr: IrRef<'ir>, attrpath: Vec<'ir, Attr<'ir>>, default: Option<IrRef<'ir>> },
|
||||
If { cond: IrRef<'ir>, consq: IrRef<'ir>, alter: IrRef<'ir> },
|
||||
Call { func: IrRef<'ir>, arg: IrRef<'ir> },
|
||||
Assert { assertion: IrRef<'ir>, expr: IrRef<'ir>, assertion_raw: String },
|
||||
ConcatStrings { parts: Vec<'ir, IrRef<'ir>>, force_string: bool },
|
||||
Path { expr: IrRef<'ir> },
|
||||
Func { body: IrRef<'ir>, param: Option<Param<'ir>>, arg: IrRef<'ir>, thunks: Vec<'ir, (ThunkId, IrRef<'ir>)> },
|
||||
TopLevel { body: IrRef<'ir>, thunks: Vec<'ir, (ThunkId, IrRef<'ir>)> },
|
||||
Arg(ArgId),
|
||||
Thunk(ExprId),
|
||||
Thunk(ThunkId),
|
||||
Builtins,
|
||||
Builtin(SymId),
|
||||
CurPos,
|
||||
ReplBinding(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),
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct ExprId(pub usize);
|
||||
pub struct ThunkId(pub usize);
|
||||
|
||||
pub type SymId = SymbolU32;
|
||||
|
||||
@@ -50,11 +52,11 @@ pub struct ArgId(pub usize);
|
||||
|
||||
/// Represents a key in an attribute path.
|
||||
#[allow(unused)]
|
||||
#[derive(Debug, TryUnwrap)]
|
||||
pub enum Attr {
|
||||
#[derive(Debug)]
|
||||
pub enum Attr<'ir> {
|
||||
/// A dynamic attribute key, which is an expression that must evaluate to a string.
|
||||
/// Example: `attrs.${key}`
|
||||
Dynamic(ExprId, TextRange),
|
||||
Dynamic(IrRef<'ir>, TextRange),
|
||||
/// A static attribute key.
|
||||
/// Example: `attrs.key`
|
||||
Str(SymId, TextRange),
|
||||
@@ -135,8 +137,8 @@ impl From<ast::UnaryOpKind> for UnOpKind {
|
||||
|
||||
/// Describes the parameters of a function.
|
||||
#[derive(Debug)]
|
||||
pub struct Param {
|
||||
pub required: Vec<(SymId, TextRange)>,
|
||||
pub optional: Vec<(SymId, TextRange)>,
|
||||
pub struct Param<'ir> {
|
||||
pub required: Vec<'ir, (SymId, TextRange)>,
|
||||
pub optional: Vec<'ir, (SymId, TextRange)>,
|
||||
pub ellipsis: bool,
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ mod tests {
|
||||
use std::fs;
|
||||
use tempfile::TempDir;
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn test_simple_file() {
|
||||
let temp = TempDir::new().unwrap();
|
||||
let file_path = temp.path().join("test.txt");
|
||||
@@ -46,7 +46,7 @@ mod tests {
|
||||
assert_eq!(hash.len(), 64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn test_directory() {
|
||||
let temp = TempDir::new().unwrap();
|
||||
fs::write(temp.path().join("a.txt"), "aaa").unwrap();
|
||||
|
||||
@@ -81,7 +81,7 @@ pub fn validate_store_path(store_dir: &str, path: &str) -> Result<()> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn test_valid_store_paths() {
|
||||
let store_dir = "/nix/store";
|
||||
let valid_paths = vec![
|
||||
@@ -100,7 +100,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn test_invalid_store_paths() {
|
||||
let store_dir = "/nix/store";
|
||||
let invalid_paths = vec![
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
use crate::utils::{eval, eval_result};
|
||||
use nix_js::value::Value;
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn arithmetic() {
|
||||
assert_eq!(eval("1 + 1"), Value::Int(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn simple_function_application() {
|
||||
assert_eq!(eval("(x: x) 1"), Value::Int(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn curried_function() {
|
||||
assert_eq!(eval("(x: y: x - y) 2 1"), Value::Int(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn rec_attrset() {
|
||||
assert_eq!(eval("rec { b = a; a = 1; }.b"), Value::Int(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn let_binding() {
|
||||
assert_eq!(eval("let b = a; a = 1; in b"), Value::Int(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn fibonacci() {
|
||||
assert_eq!(
|
||||
eval(
|
||||
@@ -36,7 +36,7 @@ fn fibonacci() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn fixed_point_combinator() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(eval("if true then 1 else 0"), Value::Int(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn conditional_false() {
|
||||
assert_eq!(eval("if false then 1 else 0"), Value::Int(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn nested_let() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert!(eval_result("{ inherit x; }").is_err());
|
||||
}
|
||||
|
||||
@@ -2,29 +2,29 @@ use crate::utils::eval;
|
||||
use nix_js::value::{AttrSet, List, Value};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_accessible() {
|
||||
let result = eval("builtins");
|
||||
assert!(matches!(result, Value::AttrSet(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_self_reference() {
|
||||
let result = eval("builtins.builtins");
|
||||
assert!(matches!(result, Value::AttrSet(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_add() {
|
||||
assert_eq!(eval("builtins.add 1 2"), Value::Int(3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_length() {
|
||||
assert_eq!(eval("builtins.length [1 2 3]"), Value::Int(3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_map() {
|
||||
assert_eq!(
|
||||
eval("builtins.map (x: x * 2) [1 2 3]"),
|
||||
@@ -32,7 +32,7 @@ fn builtins_map() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_filter() {
|
||||
assert_eq!(
|
||||
eval("builtins.filter (x: x > 1) [1 2 3]"),
|
||||
@@ -40,7 +40,7 @@ fn builtins_filter() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_attrnames() {
|
||||
let result = eval("builtins.attrNames { a = 1; b = 2; }");
|
||||
assert!(matches!(result, Value::List(_)));
|
||||
@@ -49,12 +49,12 @@ fn builtins_attrnames() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_head() {
|
||||
assert_eq!(eval("builtins.head [1 2 3]"), Value::Int(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_tail() {
|
||||
assert_eq!(
|
||||
eval("builtins.tail [1 2 3]"),
|
||||
@@ -62,17 +62,17 @@ fn builtins_tail() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_in_let() {
|
||||
assert_eq!(eval("let b = builtins; in b.add 5 3"), Value::Int(8));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_in_with() {
|
||||
assert_eq!(eval("with builtins; add 10 20"), Value::Int(30));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_nested_calls() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(eval("builtins.isList [1 2 3]"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_is_attrs() {
|
||||
assert_eq!(eval("builtins.isAttrs { a = 1; }"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_is_function() {
|
||||
assert_eq!(eval("builtins.isFunction (x: x)"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_is_null() {
|
||||
assert_eq!(eval("builtins.isNull null"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_is_bool() {
|
||||
assert_eq!(eval("builtins.isBool true"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_shadowing() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
let result = eval("builtins.builtins.builtins.add 1 1");
|
||||
assert_eq!(result, Value::Int(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_foldl() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(eval("builtins.elem 2 [1 2 3]"), Value::Bool(true));
|
||||
assert_eq!(eval("builtins.elem 5 [1 2 3]"), Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_concat_lists() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
// Numeric component comes before alpha component
|
||||
assert_eq!(
|
||||
@@ -196,7 +196,7 @@ fn builtins_compare_versions_numeric_vs_alpha() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_compare_versions_pre() {
|
||||
// "pre" is special: comes before everything except another "pre"
|
||||
assert_eq!(
|
||||
@@ -217,7 +217,7 @@ fn builtins_compare_versions_pre() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_compare_versions_alpha() {
|
||||
// Alphabetic comparison
|
||||
assert_eq!(
|
||||
@@ -230,7 +230,7 @@ fn builtins_compare_versions_alpha() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_compare_versions_symmetry() {
|
||||
// Test symmetry: compareVersions(a, b) == -compareVersions(b, a)
|
||||
assert_eq!(
|
||||
@@ -243,7 +243,7 @@ fn builtins_compare_versions_symmetry() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_compare_versions_complex() {
|
||||
// Complex version strings with multiple components
|
||||
assert_eq!(
|
||||
@@ -260,7 +260,7 @@ fn builtins_compare_versions_complex() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_generic_closure() {
|
||||
assert_eq!(
|
||||
eval(
|
||||
@@ -276,7 +276,7 @@ fn builtins_generic_closure() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_function_args() {
|
||||
assert_eq!(
|
||||
eval("builtins.functionArgs (x: 1)"),
|
||||
@@ -313,7 +313,7 @@ fn builtins_function_args() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_parse_drv_name() {
|
||||
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())));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::utils::eval_result;
|
||||
use nix_js::value::Value;
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn to_file_simple() {
|
||||
let result =
|
||||
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() {
|
||||
let result = eval_result(
|
||||
r#"
|
||||
@@ -41,7 +41,7 @@ fn to_file_with_references() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn to_file_invalid_name_with_slash() {
|
||||
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() {
|
||||
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"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn to_file_invalid_name_dotdot() {
|
||||
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"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn store_path_validation_not_in_store() {
|
||||
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() {
|
||||
let dummy_file_result = eval_result(r#"builtins.toFile "dummy.txt" "content""#)
|
||||
.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() {
|
||||
let dummy_file_result = eval_result(r#"builtins.toFile "dummy.txt" "content""#)
|
||||
.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() {
|
||||
let result = eval_result(
|
||||
r#"
|
||||
@@ -161,7 +161,7 @@ fn to_file_curried_application() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn to_file_number_conversion() {
|
||||
let result = eval_result(r#"builtins.toFile "number.txt" (builtins.toString 42)"#)
|
||||
.expect("Failed to evaluate");
|
||||
@@ -175,7 +175,7 @@ fn to_file_number_conversion() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn to_file_list_conversion() {
|
||||
let result = eval_result(
|
||||
r#"builtins.toFile "list.txt" (builtins.concatStringsSep "\n" ["line1" "line2" "line3"])"#,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::utils::{eval_deep, eval_deep_result};
|
||||
use nix_js::value::Value;
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn add_operator_preserves_derivation_context() {
|
||||
let result = eval_deep(
|
||||
r#"
|
||||
@@ -37,7 +37,7 @@ fn add_operator_preserves_derivation_context() {
|
||||
assert_eq!(result, nix_result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn derivation_minimal() {
|
||||
let result = eval_deep(
|
||||
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() {
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -97,7 +97,7 @@ fn derivation_with_args() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn derivation_to_string() {
|
||||
let result = eval_deep(
|
||||
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() {
|
||||
let result =
|
||||
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'"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn derivation_invalid_name_with_drv_suffix() {
|
||||
let result = eval_deep_result(
|
||||
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"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn derivation_missing_builder() {
|
||||
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'"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn derivation_missing_system() {
|
||||
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'"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn derivation_with_env_vars() {
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -169,7 +169,7 @@ fn derivation_with_env_vars() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn derivation_strict() {
|
||||
let result = eval_deep(
|
||||
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() {
|
||||
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() {
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -222,7 +222,7 @@ fn derivation_escaping_in_aterm() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn multi_output_two_outputs() {
|
||||
let drv = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -265,7 +265,7 @@ fn multi_output_two_outputs() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn multi_output_three_outputs() {
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -313,7 +313,7 @@ fn multi_output_three_outputs() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn multi_output_backward_compat() {
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -339,7 +339,7 @@ fn multi_output_backward_compat() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn multi_output_deterministic() {
|
||||
let result1 = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -362,7 +362,7 @@ fn multi_output_deterministic() {
|
||||
assert_eq!(result1, result2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn fixed_output_sha256_flat() {
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -399,7 +399,7 @@ fn fixed_output_sha256_flat() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn fixed_output_missing_hashalgo() {
|
||||
assert!(
|
||||
eval_deep_result(
|
||||
@@ -414,7 +414,7 @@ fn fixed_output_missing_hashalgo() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn fixed_output_recursive_mode() {
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -444,7 +444,7 @@ fn fixed_output_recursive_mode() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn fixed_output_rejects_multi_output() {
|
||||
let result = eval_deep_result(
|
||||
r#"derivation {
|
||||
@@ -462,7 +462,7 @@ fn fixed_output_rejects_multi_output() {
|
||||
assert!(err_msg.contains("fixed-output") && err_msg.contains("one"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn fixed_output_invalid_hash_mode() {
|
||||
let result = eval_deep_result(
|
||||
r#"derivation {
|
||||
@@ -479,7 +479,7 @@ fn fixed_output_invalid_hash_mode() {
|
||||
assert!(err_msg.contains("outputHashMode") && err_msg.contains("invalid"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn structured_attrs_basic() {
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -504,7 +504,7 @@ fn structured_attrs_basic() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn structured_attrs_nested() {
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -525,7 +525,7 @@ fn structured_attrs_nested() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn structured_attrs_rejects_functions() {
|
||||
let result = eval_deep_result(
|
||||
r#"derivation {
|
||||
@@ -542,7 +542,7 @@ fn structured_attrs_rejects_functions() {
|
||||
assert!(err_msg.contains("cannot convert lambda to JSON"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn structured_attrs_false() {
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -565,7 +565,7 @@ fn structured_attrs_false() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn ignore_nulls_true() {
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -587,7 +587,7 @@ fn ignore_nulls_true() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn ignore_nulls_false() {
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -610,7 +610,7 @@ fn ignore_nulls_false() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn ignore_nulls_with_structured_attrs() {
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -634,7 +634,7 @@ fn ignore_nulls_with_structured_attrs() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn all_features_combined() {
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
@@ -661,7 +661,7 @@ fn all_features_combined() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn fixed_output_with_structured_attrs() {
|
||||
let result = eval_deep(
|
||||
r#"derivation {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::utils::eval;
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn test_find_file_corepkg_fetchurl() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -15,13 +15,13 @@ fn test_find_file_corepkg_fetchurl() {
|
||||
assert!(result.to_string().contains("fetchurl.nix"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn test_lookup_path_syntax() {
|
||||
let result = eval(r#"<nix/fetchurl.nix>"#);
|
||||
assert!(result.to_string().contains("fetchurl.nix"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn test_import_corepkg() {
|
||||
let result = eval(
|
||||
r#"
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
use crate::utils::{eval, eval_result};
|
||||
use nix_js::value::{List, Value};
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn true_literal() {
|
||||
assert_eq!(eval("true"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn false_literal() {
|
||||
assert_eq!(eval("false"), Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn null_literal() {
|
||||
assert_eq!(eval("null"), Value::Null);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn map_function() {
|
||||
assert_eq!(
|
||||
eval("map (x: x * 2) [1 2 3]"),
|
||||
@@ -24,23 +24,23 @@ fn map_function() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn is_null_function() {
|
||||
assert_eq!(eval("isNull null"), Value::Bool(true));
|
||||
assert_eq!(eval("isNull 5"), Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn shadow_true() {
|
||||
assert_eq!(eval("let true = false; in true"), Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn shadow_map() {
|
||||
assert_eq!(eval("let map = x: y: x; in map 1 2"), Value::Int(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn mixed_usage() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(eval("(true: true) false"), Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn throw_function() {
|
||||
let result = eval_result("throw \"error message\"");
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn to_string_function() {
|
||||
assert_eq!(eval("toString 42"), Value::String("42".to_string()));
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
use crate::utils::{eval, eval_result};
|
||||
use nix_js::value::Value;
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn required_parameters() {
|
||||
assert_eq!(eval("({ a, b }: a + b) { a = 1; b = 2; }"), Value::Int(3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn missing_required_parameter() {
|
||||
let result = eval_result("({ a, b }: a + b) { a = 1; }");
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn all_required_parameters_present() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
let result = eval_result("({ a, b }: a + b) { a = 1; b = 2; c = 3; }");
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn ellipsis_accepts_extra_arguments() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(eval("({ a, b ? 5 }: a + b) { a = 1; }"), Value::Int(6));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn override_default_parameter() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
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() {
|
||||
assert_eq!(eval("(x: x) 42"), Value::Int(42));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn nested_function_parameters() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(eval("({ a, b ? a }: b) { a = 10; }"), Value::Int(10));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn pattern_param_multiple_references_in_default() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval("(args@{ a, b ? args.a + 10 }: b) { a = 5; }"),
|
||||
|
||||
@@ -3,7 +3,7 @@ use nix_js::context::Context;
|
||||
use nix_js::error::Source;
|
||||
use nix_js::value::Value;
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn import_absolute_path() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
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));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn import_nested() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
|
||||
@@ -32,7 +32,7 @@ fn import_nested() {
|
||||
assert_eq!(eval(&expr), Value::Int(30));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn import_relative_path() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let subdir = temp_dir.path().join("subdir");
|
||||
@@ -63,7 +63,7 @@ fn import_relative_path() {
|
||||
assert_eq!(eval(&expr), Value::Int(7));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn import_returns_function() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
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));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn import_with_complex_dependency_graph() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
|
||||
@@ -94,7 +94,7 @@ fn import_with_complex_dependency_graph() {
|
||||
|
||||
// Tests for builtins.path
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn path_with_file() {
|
||||
let mut ctx = Context::new().unwrap();
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
@@ -113,7 +113,7 @@ fn path_with_file() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn path_with_custom_name() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
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() {
|
||||
let mut ctx = Context::new().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() {
|
||||
let mut ctx = Context::new().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() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
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"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn path_nonexistent_fails() {
|
||||
let expr = r#"builtins.path { path = "/nonexistent/path/that/should/not/exist"; }"#;
|
||||
let result = eval_result(expr);
|
||||
@@ -203,7 +203,7 @@ fn path_nonexistent_fails() {
|
||||
assert!(err_msg.contains("does not exist"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn path_missing_path_param() {
|
||||
let expr = r#"builtins.path { name = "test"; }"#;
|
||||
let result = eval_result(expr);
|
||||
@@ -213,7 +213,7 @@ fn path_missing_path_param() {
|
||||
assert!(err_msg.contains("path") && err_msg.contains("required"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn path_with_sha256() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let test_file = temp_dir.path().join("hash_test.txt");
|
||||
@@ -240,7 +240,7 @@ fn path_with_sha256() {
|
||||
assert_eq!(store_path1, store_path2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn path_deterministic() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let test_file = temp_dir.path().join("deterministic.txt");
|
||||
@@ -258,7 +258,7 @@ fn path_deterministic() {
|
||||
assert_eq!(result1, result2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn read_file_type_regular_file() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
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()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn read_file_type_directory() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
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()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn read_file_type_symlink() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
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() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
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() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
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() {
|
||||
let expr = r#"builtins.readDir "/nonexistent/directory""#;
|
||||
let result = eval_result(expr);
|
||||
@@ -352,7 +352,7 @@ fn read_dir_nonexistent_fails() {
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn read_dir_on_file_fails() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let test_file = temp_dir.path().join("test.txt");
|
||||
|
||||
@@ -42,7 +42,7 @@ fn format_value(value: &Value) -> String {
|
||||
macro_rules! eval_okay_test {
|
||||
($(#[$attr:meta])* $name:ident$(, $pre:expr)?) => {
|
||||
$(#[$attr])*
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn $name() {
|
||||
$(($pre)();)?
|
||||
let test_name = concat!("eval-okay-", stringify!($name))
|
||||
@@ -74,7 +74,7 @@ macro_rules! eval_okay_test {
|
||||
|
||||
macro_rules! eval_fail_test {
|
||||
($name:ident) => {
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn $name() {
|
||||
let test_name = concat!("eval-fail-", stringify!($name))
|
||||
.replace("_", "-")
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use crate::utils::eval;
|
||||
use nix_js::value::Value;
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn large_i64_max() {
|
||||
assert_eq!(eval("9223372036854775807"), Value::Int(9223372036854775807));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn large_i64_negative() {
|
||||
assert_eq!(
|
||||
eval("-9223372036854775807"),
|
||||
@@ -14,7 +14,7 @@ fn large_i64_negative() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn large_number_arithmetic() {
|
||||
assert_eq!(
|
||||
eval("5000000000000000000 + 3000000000000000000"),
|
||||
@@ -22,33 +22,33 @@ fn large_number_arithmetic() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn is_int_with_int() {
|
||||
assert_eq!(eval("builtins.isInt 42"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn is_int_with_float() {
|
||||
assert_eq!(eval("builtins.isInt 42.0"), Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn is_float_with_int() {
|
||||
assert_eq!(eval("builtins.isFloat 42"), Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn is_float_with_float() {
|
||||
assert_eq!(eval("builtins.isFloat 42.5"), Value::Bool(true));
|
||||
assert_eq!(eval("builtins.isFloat 1.0"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn typeof_int() {
|
||||
assert_eq!(eval("builtins.typeOf 1"), Value::String("int".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn typeof_float() {
|
||||
assert_eq!(
|
||||
eval("builtins.typeOf 1.0"),
|
||||
@@ -60,17 +60,17 @@ fn typeof_float() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn int_literal() {
|
||||
assert_eq!(eval("1"), Value::Int(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn float_literal() {
|
||||
assert_eq!(eval("1."), Value::Float(1.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn int_plus_int() {
|
||||
assert_eq!(
|
||||
eval("builtins.typeOf (1 + 2)"),
|
||||
@@ -78,7 +78,7 @@ fn int_plus_int() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn int_plus_float() {
|
||||
assert_eq!(
|
||||
eval("builtins.typeOf (1 + 2.0)"),
|
||||
@@ -86,7 +86,7 @@ fn int_plus_float() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn int_times_int() {
|
||||
assert_eq!(
|
||||
eval("builtins.typeOf (3 * 4)"),
|
||||
@@ -94,7 +94,7 @@ fn int_times_int() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn int_times_float() {
|
||||
assert_eq!(
|
||||
eval("builtins.typeOf (3 * 4.0)"),
|
||||
@@ -102,25 +102,25 @@ fn int_times_float() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn integer_division() {
|
||||
assert_eq!(eval("5 / 2"), Value::Int(2));
|
||||
assert_eq!(eval("7 / 3"), Value::Int(2));
|
||||
assert_eq!(eval("10 / 3"), Value::Int(3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn float_division() {
|
||||
assert_eq!(eval("5 / 2.0"), Value::Float(2.5));
|
||||
assert_eq!(eval("7.0 / 2"), Value::Float(3.5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn negative_integer_division() {
|
||||
assert_eq!(eval("(-7) / 3"), Value::Int(-2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtin_add_with_large_numbers() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval("builtins.mul 1000000000 1000000000"),
|
||||
|
||||
@@ -2,67 +2,67 @@ use crate::utils::eval;
|
||||
use nix_js::value::{AttrSet, List, Symbol, Value};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn addition() {
|
||||
assert_eq!(eval("1 + 1"), Value::Int(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn subtraction() {
|
||||
assert_eq!(eval("2 - 1"), Value::Int(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn multiplication() {
|
||||
assert_eq!(eval("1. * 1"), Value::Float(1.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn division() {
|
||||
assert_eq!(eval("1 / 1."), Value::Float(1.));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn equality() {
|
||||
assert_eq!(eval("1 == 1"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn inequality() {
|
||||
assert_eq!(eval("1 != 1"), Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn less_than() {
|
||||
assert_eq!(eval("2 < 1"), Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn greater_than() {
|
||||
assert_eq!(eval("2 > 1"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn less_than_or_equal() {
|
||||
assert_eq!(eval("1 <= 1"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn greater_than_or_equal() {
|
||||
assert_eq!(eval("1 >= 1"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn logical_or_short_circuit() {
|
||||
assert_eq!(eval("true || (1 / 0)"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn logical_and() {
|
||||
assert_eq!(eval("true && 1 == 0"), Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn list_concatenation() {
|
||||
assert_eq!(
|
||||
eval("[ 1 2 3 ] ++ [ 4 5 6 ]"),
|
||||
@@ -70,7 +70,7 @@ fn list_concatenation() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn attrset_update() {
|
||||
assert_eq!(
|
||||
eval("{ a.b = 1; b = 2; } // { a.c = 2; }"),
|
||||
@@ -87,23 +87,23 @@ fn attrset_update() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn unary_negation() {
|
||||
assert_eq!(eval("-5"), Value::Int(-5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn logical_not() {
|
||||
assert_eq!(eval("!true"), Value::Bool(false));
|
||||
assert_eq!(eval("!false"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn select_with_default_lazy_evaluation() {
|
||||
assert_eq!(eval("{ a = 1; }.a or (1 / 0)"), Value::Int(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn select_with_default_nested_lazy() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(eval("{ a = 1; }.b or 999"), Value::Int(999));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn implication_false_false() {
|
||||
assert_eq!(eval("false -> false"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn implication_false_true() {
|
||||
assert_eq!(eval("false -> true"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn implication_true_false() {
|
||||
assert_eq!(eval("true -> false"), Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn implication_true_true() {
|
||||
assert_eq!(eval("true -> true"), Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn implication_short_circuit() {
|
||||
assert_eq!(eval("false -> (1 / 0)"), Value::Bool(true));
|
||||
}
|
||||
|
||||
@@ -1,113 +1,113 @@
|
||||
use crate::utils::{eval, eval_result};
|
||||
use nix_js::value::Value;
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn path_type_of() {
|
||||
let result = eval("builtins.typeOf ./foo");
|
||||
assert_eq!(result, Value::String("path".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn is_path_true() {
|
||||
let result = eval("builtins.isPath ./foo");
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn is_path_false_string() {
|
||||
let result = eval(r#"builtins.isPath "./foo""#);
|
||||
assert_eq!(result, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn is_path_false_number() {
|
||||
let result = eval("builtins.isPath 42");
|
||||
assert_eq!(result, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn path_concat_type() {
|
||||
// path + string = path
|
||||
let result = eval(r#"builtins.typeOf (./foo + "/bar")"#);
|
||||
assert_eq!(result, Value::String("path".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn string_path_concat_type() {
|
||||
// string + path = string
|
||||
let result = eval(r#"builtins.typeOf ("prefix-" + ./foo)"#);
|
||||
assert_eq!(result, Value::String("string".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn basename_of_path() {
|
||||
let result = eval("builtins.baseNameOf ./path/to/file.nix");
|
||||
assert!(matches!(result, Value::String(s) if s == "file.nix"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn basename_of_string() {
|
||||
let result = eval(r#"builtins.baseNameOf "/path/to/file.nix""#);
|
||||
assert_eq!(result, Value::String("file.nix".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn dir_of_path_type() {
|
||||
// dirOf preserves path type
|
||||
let result = eval("builtins.typeOf (builtins.dirOf ./path/to/file.nix)");
|
||||
assert_eq!(result, Value::String("path".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn dir_of_string_type() {
|
||||
// dirOf preserves string type
|
||||
let result = eval(r#"builtins.typeOf (builtins.dirOf "/path/to/file.nix")"#);
|
||||
assert_eq!(result, Value::String("string".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn path_equality() {
|
||||
// Same path should be equal
|
||||
let result = eval("./foo == ./foo");
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn path_not_equal_string() {
|
||||
// Paths and strings are different types - should not be equal
|
||||
let result = eval(r#"./foo == "./foo""#);
|
||||
assert_eq!(result, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn to_path_absolute() {
|
||||
// toPath with absolute path returns string
|
||||
let result = eval(r#"builtins.toPath "/foo/bar""#);
|
||||
assert_eq!(result, Value::String("/foo/bar".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn to_path_type_is_string() {
|
||||
// toPath returns a string, not a path
|
||||
let result = eval(r#"builtins.typeOf (builtins.toPath "/foo")"#);
|
||||
assert_eq!(result, Value::String("string".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn to_path_relative_fails() {
|
||||
// toPath with relative path should fail
|
||||
let result = eval_result(r#"builtins.toPath "foo/bar""#);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn to_path_empty_fails() {
|
||||
// toPath with empty string should fail
|
||||
let result = eval_result(r#"builtins.toPath """#);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn to_path_from_path_value() {
|
||||
// toPath can accept a path value too (coerces to string first)
|
||||
let result = eval("builtins.toPath ./foo");
|
||||
|
||||
@@ -3,7 +3,7 @@ use nix_js::value::{List, Value};
|
||||
|
||||
use crate::utils::eval_result;
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn match_exact_full_string() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.match "foobar" "foobar""#),
|
||||
@@ -11,12 +11,12 @@ fn match_exact_full_string() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn match_partial_returns_null() {
|
||||
assert_eq!(eval(r#"builtins.match "foo" "foobar""#), Value::Null);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn match_with_capture_groups() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.match "((.*)/)?([^/]*)\\.nix" "foobar.nix""#),
|
||||
@@ -36,7 +36,7 @@ fn match_multiple_capture_groups() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn match_with_path() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.match "[[:space:]]+([[:upper:]]+)[[:space:]]+" " foo ""#),
|
||||
@@ -69,7 +69,7 @@ fn match_posix_upper_class() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn match_quantifiers() {
|
||||
assert_eq!(
|
||||
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);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn split_non_capturing() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.split "foobar" "foobar""#),
|
||||
@@ -98,7 +98,7 @@ fn split_non_capturing() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn split_no_match() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.split "fo+" "f""#),
|
||||
@@ -106,7 +106,7 @@ fn split_no_match() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn split_with_capture_group() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.split "(fo*)" "foobar""#),
|
||||
@@ -118,7 +118,7 @@ fn split_with_capture_group() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn split_multiple_matches() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.split "(b)" "foobarbaz""#),
|
||||
@@ -132,7 +132,7 @@ fn split_multiple_matches() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn split_with_multiple_groups() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.split "(a)|(c)" "abc""#),
|
||||
@@ -161,7 +161,7 @@ fn split_with_optional_groups() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn split_greedy_matching() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.split "(o+)" "oooofoooo""#),
|
||||
@@ -175,7 +175,7 @@ fn split_greedy_matching() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn split_posix_classes() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.split "([[:upper:]]+)" " FOO ""#),
|
||||
@@ -187,7 +187,7 @@ fn split_posix_classes() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn replace_basic() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.replaceStrings ["o"] ["a"] "foobar""#),
|
||||
@@ -195,7 +195,7 @@ fn replace_basic() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn replace_with_empty() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.replaceStrings ["o"] [""] "foobar""#),
|
||||
@@ -203,7 +203,7 @@ fn replace_with_empty() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn replace_multiple_patterns() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.replaceStrings [""] ["X"] "abc""#),
|
||||
@@ -227,7 +227,7 @@ fn replace_empty_pattern() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn replace_empty_pattern_empty_string() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.replaceStrings [""] ["X"] """#),
|
||||
@@ -235,7 +235,7 @@ fn replace_empty_pattern_empty_string() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn replace_simple_char() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.replaceStrings ["-"] ["_"] "a-b""#),
|
||||
@@ -243,7 +243,7 @@ fn replace_simple_char() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn replace_longer_pattern() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.replaceStrings ["oo"] ["u"] "foobar""#),
|
||||
@@ -251,13 +251,13 @@ fn replace_longer_pattern() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn replace_different_lengths() {
|
||||
let result = eval_result(r#"builtins.replaceStrings ["a" "b"] ["x"] "test""#);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn split_version_simple() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.splitVersion "1.2.3""#),
|
||||
@@ -269,7 +269,7 @@ fn split_version_simple() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn split_version_with_pre() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.splitVersion "2.3a""#),
|
||||
@@ -295,7 +295,7 @@ fn split_version_with_letters() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn split_version_with_dashes() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.splitVersion "2.3-beta1""#),
|
||||
@@ -308,7 +308,7 @@ fn split_version_with_dashes() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn split_version_empty() {
|
||||
assert_eq!(
|
||||
eval(r#"builtins.splitVersion """#),
|
||||
|
||||
@@ -6,13 +6,13 @@ fn eval(expr: &str) -> Value {
|
||||
eval_result(expr).unwrap_or_else(|e| panic!("{}", e))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn hascontext_plain_string() {
|
||||
let result = eval(r#"builtins.hasContext "hello""#);
|
||||
assert_eq!(result, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn hascontext_derivation_output() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -24,7 +24,7 @@ fn hascontext_derivation_output() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn getcontext_plain_string() {
|
||||
let result = eval(r#"builtins.getContext "hello""#);
|
||||
match result {
|
||||
@@ -35,7 +35,7 @@ fn getcontext_plain_string() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn getcontext_derivation_output() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -60,7 +60,7 @@ fn getcontext_derivation_output() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn unsafediscardstringcontext() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -74,7 +74,7 @@ fn unsafediscardstringcontext() {
|
||||
assert_eq!(result, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn unsafediscardstringcontext_preserves_value() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -88,7 +88,7 @@ fn unsafediscardstringcontext_preserves_value() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn appendcontext_basic() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -102,7 +102,7 @@ fn appendcontext_basic() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn appendcontext_preserves_value() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -116,7 +116,7 @@ fn appendcontext_preserves_value() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn string_concat_merges_context() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -133,7 +133,7 @@ fn string_concat_merges_context() {
|
||||
assert_eq!(result, Value::Int(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn string_add_merges_context() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -150,7 +150,7 @@ fn string_add_merges_context() {
|
||||
assert_eq!(result, Value::Int(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn context_in_derivation_args() {
|
||||
let mut ctx = Context::new().unwrap();
|
||||
let result = ctx
|
||||
@@ -179,7 +179,7 @@ fn context_in_derivation_args() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn context_in_derivation_env() {
|
||||
let mut ctx = Context::new().unwrap();
|
||||
let result = ctx
|
||||
@@ -208,7 +208,7 @@ fn context_in_derivation_env() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn tostring_preserves_context() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -221,7 +221,7 @@ fn tostring_preserves_context() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn interpolation_derivation_returns_outpath() {
|
||||
let mut ctx = Context::new().unwrap();
|
||||
let result = ctx
|
||||
@@ -244,7 +244,7 @@ fn interpolation_derivation_returns_outpath() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn interpolation_derivation_has_context() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -256,7 +256,7 @@ fn interpolation_derivation_has_context() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn interpolation_derivation_context_correct() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -277,7 +277,7 @@ fn interpolation_derivation_context_correct() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn interpolation_multiple_derivations() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -292,7 +292,7 @@ fn interpolation_multiple_derivations() {
|
||||
assert_eq!(result, Value::Int(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn interpolation_derivation_equals_tostring() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -304,7 +304,7 @@ fn interpolation_derivation_equals_tostring() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn substring_preserves_context() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -318,7 +318,7 @@ fn substring_preserves_context() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn substring_zero_length_preserves_context() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -332,7 +332,7 @@ fn substring_zero_length_preserves_context() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn substring_zero_length_empty_value() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -346,7 +346,7 @@ fn substring_zero_length_empty_value() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
#[allow(non_snake_case)]
|
||||
fn concatStringsSep_preserves_context() {
|
||||
let result = eval(
|
||||
@@ -363,7 +363,7 @@ fn concatStringsSep_preserves_context() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
#[allow(non_snake_case)]
|
||||
fn concatStringsSep_merges_contexts() {
|
||||
let result = eval(
|
||||
@@ -381,7 +381,7 @@ fn concatStringsSep_merges_contexts() {
|
||||
assert_eq!(result, Value::Int(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
#[allow(non_snake_case)]
|
||||
fn concatStringsSep_separator_has_context() {
|
||||
let result = eval(
|
||||
@@ -396,7 +396,7 @@ fn concatStringsSep_separator_has_context() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
#[allow(non_snake_case)]
|
||||
fn replaceStrings_input_context_preserved() {
|
||||
let result = eval(
|
||||
@@ -411,7 +411,7 @@ fn replaceStrings_input_context_preserved() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
#[allow(non_snake_case)]
|
||||
fn replaceStrings_replacement_context_collected() {
|
||||
let result = eval(
|
||||
@@ -426,7 +426,7 @@ fn replaceStrings_replacement_context_collected() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
#[allow(non_snake_case)]
|
||||
fn replaceStrings_merges_contexts() {
|
||||
let result = eval(
|
||||
@@ -444,7 +444,7 @@ fn replaceStrings_merges_contexts() {
|
||||
assert_eq!(result, Value::Int(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
#[allow(non_snake_case)]
|
||||
fn replaceStrings_lazy_evaluation_context() {
|
||||
let result = eval(
|
||||
@@ -459,7 +459,7 @@ fn replaceStrings_lazy_evaluation_context() {
|
||||
assert_eq!(result, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
#[allow(non_snake_case)]
|
||||
fn baseNameOf_preserves_context() {
|
||||
let result = eval(
|
||||
@@ -474,7 +474,7 @@ fn baseNameOf_preserves_context() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn split_no_match_preserves_context() {
|
||||
let result = eval(
|
||||
r#"
|
||||
@@ -488,7 +488,7 @@ fn split_no_match_preserves_context() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_path_has_context() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let test_file = temp_dir.path().join("test.txt");
|
||||
@@ -502,7 +502,7 @@ fn builtins_path_has_context() {
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn builtins_path_context_tracked_in_structured_attrs_derivation() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
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() {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let test_file = temp_dir.path().join("dep.txt");
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use crate::utils::eval;
|
||||
use nix_js::value::Value;
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn non_recursive_bindings() {
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval(
|
||||
@@ -40,7 +40,7 @@ fn mutual_recursion_simple() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn mutual_recursion_even_odd() {
|
||||
assert_eq!(
|
||||
eval(
|
||||
@@ -50,7 +50,7 @@ fn mutual_recursion_even_odd() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn mixed_recursive_and_non_recursive() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval(
|
||||
@@ -68,12 +68,12 @@ fn mixed_with_multiple_non_recursive() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn rec_attrset_non_recursive() {
|
||||
assert_eq!(eval("rec { x = 1; y = 2; z = x + y; }.z"), Value::Int(3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn rec_attrset_recursive() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval(
|
||||
@@ -107,7 +107,7 @@ fn three_way_mutual_recursion() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn complex_mixed_dependencies() {
|
||||
assert_eq!(
|
||||
eval(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::utils::{eval, eval_result};
|
||||
use nix_js::value::Value;
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn string_returns_as_is() {
|
||||
assert_eq!(
|
||||
eval(r#"toString "hello""#),
|
||||
@@ -9,32 +9,32 @@ fn string_returns_as_is() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn integer_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 0"), Value::String("0".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn float_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 (-2.5)"), Value::String("-2.5".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn bool_to_string() {
|
||||
assert_eq!(eval("toString true"), Value::String("1".to_string()));
|
||||
assert_eq!(eval("toString false"), Value::String("".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn null_to_string() {
|
||||
assert_eq!(eval("toString null"), Value::String("".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn simple_list_to_string() {
|
||||
assert_eq!(eval("toString [1 2 3]"), Value::String("1 2 3".to_string()));
|
||||
assert_eq!(
|
||||
@@ -43,7 +43,7 @@ fn simple_list_to_string() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn nested_list_flattens() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval("toString [1 [] [] 2]"),
|
||||
@@ -71,7 +71,7 @@ fn list_with_multiple_empty_lists() {
|
||||
assert_eq!(eval("toString [[] [] 1]"), Value::String("1".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn list_with_bool_and_null() {
|
||||
assert_eq!(
|
||||
eval("toString [true false null]"),
|
||||
@@ -83,7 +83,7 @@ fn list_with_bool_and_null() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn mixed_type_list() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval(
|
||||
@@ -117,7 +117,7 @@ fn attrs_to_string_self_reference() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn attrs_to_string_priority() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval(
|
||||
@@ -135,7 +135,7 @@ fn derivation_like_object() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn string_interpolation_with_int() {
|
||||
assert_eq!(
|
||||
eval(r#""value: ${toString 42}""#),
|
||||
@@ -143,7 +143,7 @@ fn string_interpolation_with_int() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn string_interpolation_with_list() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval(r#"toString (toString 42)"#),
|
||||
@@ -159,7 +159,7 @@ fn nested_to_string_calls() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn to_string_in_let_binding() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(eval(r#"toString """#), Value::String("".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn empty_list() {
|
||||
assert_eq!(eval("toString []"), Value::String("".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn to_string_preserves_spaces_in_strings() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval(r#"toString ["" "" ""]"#),
|
||||
@@ -193,7 +193,7 @@ fn list_of_empty_strings() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn deeply_nested_lists() {
|
||||
assert_eq!(
|
||||
eval("toString [[[1] [2]] [[3] [4]]]"),
|
||||
@@ -201,7 +201,7 @@ fn deeply_nested_lists() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn list_with_nested_empty_lists() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
let result = eval_result(r#"toString { foo = "bar"; }"#);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn function_to_string_fails() {
|
||||
let result = eval_result("toString (x: x)");
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test_log::test]
|
||||
fn to_string_method_must_return_string() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
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() {
|
||||
assert_eq!(
|
||||
eval(r#"toString ["a" "b"]"#),
|
||||
|
||||
Reference in New Issue
Block a user