From 9aee36a0e2c8f8e5eda59d061bc078367539ecfc Mon Sep 17 00:00:00 2001 From: imxyy_soope_ Date: Sun, 18 Jan 2026 16:35:20 +0800 Subject: [PATCH] fix: relative path resolution comma operator... --- nix-js/runtime-ts/src/builtins/io.ts | 6 ++++-- nix-js/runtime-ts/src/builtins/type-check.ts | 3 ++- nix-js/src/codegen.rs | 4 ++-- nix-js/src/context.rs | 2 -- nix-js/src/runtime.rs | 18 +++++++++++++++--- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/nix-js/runtime-ts/src/builtins/io.ts b/nix-js/runtime-ts/src/builtins/io.ts index 7183747..e264bd2 100644 --- a/nix-js/runtime-ts/src/builtins/io.ts +++ b/nix-js/runtime-ts/src/builtins/io.ts @@ -11,6 +11,7 @@ import { coerceToPath, coerceToString, StringCoercionMode } from "./conversion"; import { getPathValue } from "../path"; import type { NixStringContext, StringWithContext } from "../string-context"; import { mkStringWithContext } from "../string-context"; +import { isPath } from "./type-check"; export const importFunc = (path: NixValue): NixValue => { const context: NixStringContext = new Set(); @@ -143,8 +144,9 @@ export const fetchTarball = (args: NixValue): string => { export const fetchGit = (args: NixValue): NixAttrs => { const forced = force(args); - if (typeof forced === "string") { - const result: FetchGitResult = Deno.core.ops.op_fetch_git(forced, null, null, false, false, false, null); + if (typeof forced === "string" || isPath(forced)) { + const path = coerceToPath(forced); + const result: FetchGitResult = Deno.core.ops.op_fetch_git(path, null, null, false, false, false, null); return { outPath: result.out_path, rev: result.rev, diff --git a/nix-js/runtime-ts/src/builtins/type-check.ts b/nix-js/runtime-ts/src/builtins/type-check.ts index 2074eed..43fa0e3 100644 --- a/nix-js/runtime-ts/src/builtins/type-check.ts +++ b/nix-js/runtime-ts/src/builtins/type-check.ts @@ -5,6 +5,7 @@ import { HAS_CONTEXT, isNixPath, + NixPath, type NixAttrs, type NixBool, type NixFloat, @@ -40,7 +41,7 @@ export const isList = (e: NixValue): e is NixList => Array.isArray(force(e)); export const isNull = (e: NixValue): e is NixNull => force(e) === null; -export const isPath = (e: NixValue): boolean => { +export const isPath = (e: NixValue): e is NixPath => { const val = force(e); return isNixPath(val); }; diff --git a/nix-js/src/codegen.rs b/nix-js/src/codegen.rs index 3181553..0e1c892 100644 --- a/nix-js/src/codegen.rs +++ b/nix-js/src/codegen.rs @@ -7,12 +7,12 @@ use crate::ir::*; pub(crate) fn compile(expr: &Ir, ctx: &impl CodegenContext) -> String { let code = expr.compile(ctx); let debug_prefix = if std::env::var("NIX_JS_DEBUG_THUNKS").is_ok() { - "Nix.DEBUG_THUNKS.enabled=true," + "Nix.DEBUG_THUNKS.enabled=true;" } else { "" }; let cur_dir = ctx.get_current_dir().display().to_string().escape_quote(); - format!("({}currentDir={},{})", debug_prefix, cur_dir, code) + format!("(()=>{{{}const currentDir={};return {}}})()", debug_prefix, cur_dir, code) } trait Compile { diff --git a/nix-js/src/context.rs b/nix-js/src/context.rs index 8d23475..0b216b9 100644 --- a/nix-js/src/context.rs +++ b/nix-js/src/context.rs @@ -70,7 +70,6 @@ impl Context { Ok(Self { ctx, runtime, store }) } - #[tracing::instrument(skip(self), fields(expr_len = expr.len()))] pub fn eval_code(&mut self, expr: &str) -> Result { tracing::info!("Starting evaluation"); self.ctx.current_file = Some( @@ -196,7 +195,6 @@ impl Ctx { .expect("current_file doesn't have a parent dir") } - #[tracing::instrument(skip(self), fields(expr_len = expr.len()))] fn compile_code(&mut self, expr: &str) -> Result { tracing::debug!("Parsing Nix expression"); let root = rnix::Root::parse(expr); diff --git a/nix-js/src/runtime.rs b/nix-js/src/runtime.rs index 1c2f0da..9844c3d 100644 --- a/nix-js/src/runtime.rs +++ b/nix-js/src/runtime.rs @@ -121,13 +121,24 @@ fn op_resolve_path( #[string] current_dir: String, #[string] path: String, ) -> std::result::Result { + let _span = tracing::debug_span!("op_resolve_path").entered(); + tracing::debug!(current_dir, path); + // If already absolute, return as-is if path.starts_with('/') { return Ok(path); } - // Resolve relative path against current file directory (or CWD) - let current_dir = PathBuf::from(current_dir).join(&path); + let current_dir = if !path.starts_with("~/") { + let mut dir = PathBuf::from(current_dir); + dir.push(path); + dir + } else { + let mut dir = std::env::home_dir() + .ok_or("home dir not defined")?; + dir.push(&path[2..]); + dir + }; let mut normalized = PathBuf::new(); for component in current_dir.components() { match component { @@ -140,6 +151,7 @@ fn op_resolve_path( Component::Normal(c) => normalized.push(c), } } + tracing::debug!(normalized = normalized.display().to_string()); Ok(normalized.to_string_lossy().to_string()) } @@ -305,7 +317,7 @@ fn op_store_path( state: &mut OpState, #[string] path: String, ) -> std::result::Result { - use crate::store::{validate_store_path, StoreBackend}; + use crate::store::{StoreBackend, validate_store_path}; use std::sync::Arc; let store = state.borrow::>();