From 13874ca6ca24ff62b7b14c0bd1572b642246d166 Mon Sep 17 00:00:00 2001 From: imxyy_soope_ Date: Sat, 31 Jan 2026 13:53:02 +0800 Subject: [PATCH] fix: structuredAttrs --- nix-js/runtime-ts/src/builtins/derivation.ts | 71 +++++++++++--------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/nix-js/runtime-ts/src/builtins/derivation.ts b/nix-js/runtime-ts/src/builtins/derivation.ts index bb9c879..ed56779 100644 --- a/nix-js/runtime-ts/src/builtins/derivation.ts +++ b/nix-js/runtime-ts/src/builtins/derivation.ts @@ -90,6 +90,35 @@ const extractArgs = (attrs: NixAttrs, outContext: NixStringContext): string[] => return argsList.map((a) => coerceToString(a, StringCoercionMode.ToString, false, outContext)); }; +const structuredAttrsExcludedKeys = new Set([ + "__structuredAttrs", + "__ignoreNulls", + "__contentAddressed", + "impure", + "args", +]); + +const specialAttrs = new Set([ + "name", + "builder", + "system", + "args", + "outputs", + "__structuredAttrs", + "__ignoreNulls", + "__contentAddressed", + "impure", +]); + +const sortedJsonStringify = (obj: Record): string => { + const sortedKeys = Object.keys(obj).sort(); + const sortedObj: Record = {}; + for (const key of sortedKeys) { + sortedObj[key] = obj[key]; + } + return JSON.stringify(sortedObj); +}; + const extractEnv = ( attrs: NixAttrs, structuredAttrs: boolean, @@ -97,24 +126,12 @@ const extractEnv = ( outContext: NixStringContext, drvName: string, ): Map => { - const specialAttrs = new Set([ - "name", - "builder", - "system", - "args", - "outputs", - "__structuredAttrs", - "__ignoreNulls", - "__contentAddressed", - "impure", - ]); - const env = new Map(); if (structuredAttrs) { const jsonAttrs: Record = {}; for (const [key, value] of Object.entries(attrs)) { - if (!specialAttrs.has(key)) { + if (!structuredAttrsExcludedKeys.has(key)) { const forcedValue = force(value); if (ignoreNulls && forcedValue === null) { continue; @@ -165,7 +182,7 @@ const extractEnv = ( ); } } - env.set("__json", JSON.stringify(jsonAttrs)); + env.set("__json", sortedJsonStringify(jsonAttrs)); } else { for (const [key, value] of Object.entries(attrs)) { if (!specialAttrs.has(key)) { @@ -236,11 +253,13 @@ export const derivationStrict = (args: NixValue): NixAttrs => { const drvArgs = extractArgs(attrs, collectedContext); const env = extractEnv(attrs, structuredAttrs, ignoreNulls, collectedContext, drvName); - env.set("name", drvName); - env.set("builder", builder); - env.set("system", platform); - if (outputs.length > 1 || outputs[0] !== "out") { - env.set("outputs", outputs.join(" ")); + if (!structuredAttrs) { + env.set("name", drvName); + env.set("builder", builder); + env.set("system", platform); + if (outputs.length > 1 || outputs[0] !== "out") { + env.set("outputs", outputs.join(" ")); + } } const { inputDrvs, inputSrcs } = extractInputDrvsAndSrcs(collectedContext); @@ -351,18 +370,6 @@ export const derivationStrict = (args: NixValue): NixAttrs => { return result; }; -const specialAttrs = new Set([ - "name", - "builder", - "system", - "args", - "outputs", - "__structuredAttrs", - "__ignoreNulls", - "__contentAddressed", - "impure", -]); - export const derivation = (args: NixValue): NixAttrs => { const attrs = forceAttrs(args); @@ -385,7 +392,7 @@ export const derivation = (args: NixValue): NixAttrs => { const outputsList = outputs.map(outputToAttrListElement); - for (const { name: outputName, value } of outputsList) { + for (const { name: outputName } of outputsList) { commonAttrs[outputName] = createThunk( () => outputsList.find((o) => o.name === outputName)!.value, `output_${outputName}`,