From 6838f9a0cf7db60f40a09df41400148b32bc9123 Mon Sep 17 00:00:00 2001 From: imxyy_soope_ Date: Sat, 31 Jan 2026 16:46:14 +0800 Subject: [PATCH] fix: unsafeGetAttrPos call on functionArgs --- nix-js/runtime-ts/src/builtins/misc.ts | 10 +++++++++- nix-js/runtime-ts/src/types.ts | 7 +++++-- nix-js/src/codegen.rs | 10 +++++++--- nix-js/src/ir.rs | 4 ++-- nix-js/src/ir/utils.rs | 22 ++++++++++++---------- 5 files changed, 35 insertions(+), 18 deletions(-) diff --git a/nix-js/runtime-ts/src/builtins/misc.ts b/nix-js/runtime-ts/src/builtins/misc.ts index a3a488d..7499c54 100644 --- a/nix-js/runtime-ts/src/builtins/misc.ts +++ b/nix-js/runtime-ts/src/builtins/misc.ts @@ -3,7 +3,7 @@ */ import { force } from "../thunk"; -import { CatchableError } from "../types"; +import { CatchableError, ATTR_POSITIONS } from "../types"; import type { NixAttrs, NixBool, NixStrictValue, NixValue } from "../types"; import { forceList, forceAttrs, forceFunction, forceStringValue, forceString, forceStringNoCtx } from "../type-assert"; import * as context from "./context"; @@ -165,6 +165,14 @@ export const functionArgs = (f: NixValue): NixAttrs => { for (const key of func.args!.optional) { ret[key] = true; } + const positions = func.args!.positions; + if (positions && Object.keys(positions).length > 0) { + Object.defineProperty(ret, ATTR_POSITIONS, { + value: positions, + enumerable: false, + writable: false, + }); + } return ret; } return {}; diff --git a/nix-js/runtime-ts/src/types.ts b/nix-js/runtime-ts/src/types.ts index 0d42a79..8a06375 100644 --- a/nix-js/runtime-ts/src/types.ts +++ b/nix-js/runtime-ts/src/types.ts @@ -39,9 +39,11 @@ export class NixArgs { optional: string[]; allowed: Set; ellipsis: boolean; - constructor(required: string[], optional: string[], ellipsis: boolean) { + positions: Record; + constructor(required: string[], optional: string[], positions: Record, ellipsis: boolean) { this.required = required; this.optional = optional; + this.positions = positions; this.ellipsis = ellipsis; this.allowed = new Set(required.concat(optional)); } @@ -67,10 +69,11 @@ export const mkFunction = ( f: (arg: NixValue) => NixValue, required: string[], optional: string[], + positions: Record, ellipsis: boolean, ): NixFunction => { const func = f as NixFunction; - func.args = new NixArgs(required, optional, ellipsis); + func.args = new NixArgs(required, optional, positions, ellipsis); return func; }; diff --git a/nix-js/src/codegen.rs b/nix-js/src/codegen.rs index 7e909f1..ee3a375 100644 --- a/nix-js/src/codegen.rs +++ b/nix-js/src/codegen.rs @@ -424,14 +424,18 @@ impl Compile for Func { } code!(buf, ctx; ",[" - joined(required.iter(), ",", |ctx: &Ctx, buf, &sym| { + joined(required.iter(), ",", |ctx: &Ctx, buf, &(sym, _)| { code!(buf, ctx; quoted(ctx.get_sym(sym))); }) "],[" - joined(optional.iter(), ",", |ctx: &Ctx, buf, &sym| { + joined(optional.iter(), ",", |ctx: &Ctx, buf, &(sym, _)| { code!(buf, ctx; quoted(ctx.get_sym(sym))); }) - "]," + "],{" + joined(required.iter().chain(optional.iter()), ",", |ctx: &Ctx, buf, &(sym, span)| { + code!(buf, ctx; quoted(ctx.get_sym(sym)), ":", span); + }) + "}," ); code!(buf, "{})", ellipsis); } else { diff --git a/nix-js/src/ir.rs b/nix-js/src/ir.rs index b0fe989..4ba0209 100644 --- a/nix-js/src/ir.rs +++ b/nix-js/src/ir.rs @@ -173,7 +173,7 @@ impl From for UnOpKind { /// Describes the parameters of a function. #[derive(Debug)] pub struct Param { - pub required: Vec, - pub optional: Vec, + pub required: Vec<(SymId, TextRange)>, + pub optional: Vec<(SymId, TextRange)>, pub ellipsis: bool, } diff --git a/nix-js/src/ir/utils.rs b/nix-js/src/ir/utils.rs index f9651f8..08e0460 100644 --- a/nix-js/src/ir/utils.rs +++ b/nix-js/src/ir/utils.rs @@ -474,8 +474,8 @@ pub fn downgrade_attrpath( pub struct PatternBindings { pub body: ExprId, - pub required: Vec, - pub optional: Vec, + pub required: Vec<(SymId, TextRange)>, + pub optional: Vec<(SymId, TextRange)>, } /// Helper function for Lambda pattern parameters. @@ -529,14 +529,16 @@ where binding_keys.push(alias_sym); } - let (required, optional) = params.iter().partition_map(|Param { sym, default, .. }| { - use itertools::Either::*; - if default.is_none() { - Left(sym) - } else { - Right(sym) - } - }); + let (required, optional) = params + .iter() + .partition_map(|Param { sym, sym_span, default, .. }| { + use itertools::Either::*; + if default.is_none() { + Left((*sym, *sym_span)) + } else { + Right((*sym, *sym_span)) + } + }); let slots: Vec<_> = ctx.reserve_slots(binding_keys.len()).collect(); let let_bindings: HashMap<_, _> = binding_keys