From a68681b4f5165d97d7ffe25e398cb98a80c1b9e2 Mon Sep 17 00:00:00 2001 From: imxyy_soope_ Date: Sat, 31 Jan 2026 20:19:00 +0800 Subject: [PATCH] fix: derivation references --- nix-js/runtime-ts/src/builtins/derivation.ts | 21 +++++++++++++++----- nix-js/runtime-ts/src/types/global.d.ts | 1 + nix-js/src/nix_hash.rs | 14 +++++++++++++ nix-js/src/runtime.rs | 15 ++++++++++++++ 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/nix-js/runtime-ts/src/builtins/derivation.ts b/nix-js/runtime-ts/src/builtins/derivation.ts index 81d2052..12e65df 100644 --- a/nix-js/runtime-ts/src/builtins/derivation.ts +++ b/nix-js/runtime-ts/src/builtins/derivation.ts @@ -46,7 +46,7 @@ const validateBuilder = (attrs: NixAttrs, outContext: NixStringContext): string if (!("builder" in attrs)) { throw new Error("derivation: missing required attribute 'builder'"); } - return coerceToString(attrs.builder, StringCoercionMode.ToString, false, outContext); + return coerceToString(attrs.builder, StringCoercionMode.ToString, true, outContext); }; const validateSystem = (attrs: NixAttrs): string => { @@ -87,7 +87,7 @@ const extractArgs = (attrs: NixAttrs, outContext: NixStringContext): string[] => return []; } const argsList = forceList(attrs.args); - return argsList.map((a) => coerceToString(a, StringCoercionMode.ToString, false, outContext)); + return argsList.map((a) => coerceToString(a, StringCoercionMode.ToString, true, outContext)); }; const structuredAttrsExcludedKeys = new Set([ @@ -190,7 +190,7 @@ const extractEnv = ( if (ignoreNulls && forcedValue === null) { continue; } - env.set(key, coerceToString(value, StringCoercionMode.ToString, false, outContext)); + env.set(key, coerceToString(value, StringCoercionMode.ToString, true, outContext)); } } } @@ -281,6 +281,17 @@ export const derivationStrict = (args: NixValue): NixAttrs => { const { inputDrvs, inputSrcs } = extractInputDrvsAndSrcs(collectedContext); + const collectDrvReferences = (): string[] => { + const refs = new Set(); + for (const src of inputSrcs) { + refs.add(src); + } + for (const drvPath of inputDrvs.keys()) { + refs.add(drvPath); + } + return Array.from(refs).sort(); + }; + let outputInfos: Map; let drvPath: string; @@ -318,7 +329,7 @@ export const derivationStrict = (args: NixValue): NixAttrs => { }; const finalAterm = generateAterm(finalDrv); const finalDrvHash = Deno.core.ops.op_sha256_hex(finalAterm); - drvPath = Deno.core.ops.op_make_store_path("text", finalDrvHash, `${drvName}.drv`); + drvPath = Deno.core.ops.op_make_text_store_path(finalDrvHash, `${drvName}.drv`, collectDrvReferences()); } else { const maskedOutputs = new Map( outputs.map((o) => [ @@ -369,7 +380,7 @@ export const derivationStrict = (args: NixValue): NixAttrs => { const finalAterm = generateAterm(finalDrv); const finalDrvHash = Deno.core.ops.op_sha256_hex(finalAterm); - drvPath = Deno.core.ops.op_make_store_path("text", finalDrvHash, `${drvName}.drv`); + drvPath = Deno.core.ops.op_make_text_store_path(finalDrvHash, `${drvName}.drv`, collectDrvReferences()); } const result: NixAttrs = {}; diff --git a/nix-js/runtime-ts/src/types/global.d.ts b/nix-js/runtime-ts/src/types/global.d.ts index 948ce0d..f38d87d 100644 --- a/nix-js/runtime-ts/src/types/global.d.ts +++ b/nix-js/runtime-ts/src/types/global.d.ts @@ -45,6 +45,7 @@ declare global { function op_make_placeholder(output: string): string; function op_decode_span(span: string): { file: string | null; line: number | null; column: number | null }; function op_make_store_path(ty: string, hash_hex: string, name: string): string; + function op_make_text_store_path(hash_hex: string, name: string, references: string[]): string; function op_output_path_name(drv_name: string, output_name: string): string; function op_make_fixed_output_path( hash_algo: string, diff --git a/nix-js/src/nix_hash.rs b/nix-js/src/nix_hash.rs index 558602d..ec3cff8 100644 --- a/nix-js/src/nix_hash.rs +++ b/nix-js/src/nix_hash.rs @@ -93,6 +93,20 @@ pub fn make_store_path(store_dir: &str, ty: &str, hash_hex: &str, name: &str) -> format!("{}/{}-{}", store_dir, encoded, name) } +pub fn make_text_store_path( + store_dir: &str, + hash_hex: &str, + name: &str, + references: &[String], +) -> String { + let mut ty = String::from("text"); + for reference in references { + ty.push(':'); + ty.push_str(reference); + } + make_store_path(store_dir, &ty, hash_hex, name) +} + pub fn output_path_name(drv_name: &str, output_name: &str) -> String { if output_name == "out" { drv_name.to_string() diff --git a/nix-js/src/runtime.rs b/nix-js/src/runtime.rs index eae924f..8bd243d 100644 --- a/nix-js/src/runtime.rs +++ b/nix-js/src/runtime.rs @@ -52,6 +52,7 @@ fn runtime_extension() -> Extension { op_make_placeholder(), op_decode_span::(), op_make_store_path::(), + op_make_text_store_path::(), op_output_path_name(), op_make_fixed_output_path::(), op_add_path::(), @@ -360,6 +361,20 @@ fn op_make_store_path( crate::nix_hash::make_store_path(store_dir, &ty, &hash_hex, &name) } +#[deno_core::op2] +#[string] +fn op_make_text_store_path( + state: &mut OpState, + #[string] hash_hex: String, + #[string] name: String, + #[serde] references: Vec, +) -> String { + let ctx: &Ctx = state.get_ctx(); + let store = ctx.get_store(); + let store_dir = store.get_store_dir(); + crate::nix_hash::make_text_store_path(store_dir, &hash_hex, &name, &references) +} + #[deno_core::op2] #[string] fn op_output_path_name(#[string] drv_name: String, #[string] output_name: String) -> String {